Anda dapat menggunakan SDK Tablestore untuk mengkueri data bidang bersarang tingkat tunggal dan multi-level. Saat melakukan kueri bersarang, Anda dapat menggunakan fitur sorotan untuk menyoroti string kueri dalam hasil kueri. Untuk informasi lebih lanjut, lihat Highlight.
Kueri bidang bersarang tingkat tunggal
Kode sampel berikut memberikan contoh cara mengkueri baris di mana nilai kolom col_nested.nested_1 adalah tablestore. Dalam contoh ini, kolom bersarang bernama col_nested mencakup subkolom nested_1 dan nested_2.
private static void nestedQuery(SyncClient client) {
SearchQuery searchQuery = new SearchQuery();
NestedQuery nestedQuery = new NestedQuery(); // Atur tipe kueri ke NestedQuery.
nestedQuery.setPath("col_nested"); // Tentukan jalur kolom bersarang.
TermQuery termQuery = new TermQuery(); // Tentukan subkueri untuk melakukan kueri bersarang.
termQuery.setFieldName("col_nested.nested_1"); // Tentukan nama kolom. Nama tersebut harus mencakup jalur kolom bersarang.
termQuery.setTerm(ColumnValue.fromString("tablestore")); // Tentukan nilai yang ingin Anda gunakan untuk mencocokkan nilai kolom.
nestedQuery.setQuery(termQuery);
nestedQuery.setScoreMode(ScoreMode.None);
searchQuery.setQuery(nestedQuery);
//searchQuery.setGetTotalCount(true);// Atur parameter GetTotalCount ke true untuk mengembalikan jumlah total baris yang cocok.
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Anda dapat mengonfigurasi parameter columnsToGet untuk menentukan kolom yang akan dikembalikan atau menentukan bahwa semua kolom dikembalikan. Jika Anda tidak mengonfigurasi parameter ini, hanya kolom kunci utama yang dikembalikan.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Tentukan bahwa semua kolom dikembalikan.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Tentukan kolom yang ingin Anda kembalikan.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Tentukan bahwa jumlah total baris yang cocok bukan jumlah baris yang dikembalikan yang ditampilkan.
System.out.println("Row: " + resp.getRows());
}
Kueri bidang bersarang multi-level
Kode sampel berikut memberikan contoh cara mengkueri baris di mana nilai kolom col_nested.nested_2.nested_2_2 adalah tablestore. Dalam contoh ini, kolom bersarang bernama col_nested mencakup subkolom nested_1 dan nested_2. Subkolom nested_2 mencakup kolom nested_2_1 dan nested_2_2.
private static void nestedQuery(SyncClient client) {
SearchQuery searchQuery = new SearchQuery();
NestedQuery nestedQuery = new NestedQuery(); // Atur tipe kueri ke NestedQuery.
nestedQuery.setPath("col_nested.nested_2"); // Tentukan jalur kolom bersarang, yaitu jalur induk kolom yang ingin Anda kueri.
TermQuery termQuery = new TermQuery(); // Tentukan subkueri untuk melakukan kueri bersarang.
termQuery.setFieldName("col_nested.nested_2.nested_2_2"); // Tentukan nama kolom. Nama tersebut harus mencakup jalur kolom bersarang.
termQuery.setTerm(ColumnValue.fromString("tablestore")); // Tentukan nilai yang ingin Anda gunakan untuk mencocokkan nilai kolom.
nestedQuery.setQuery(termQuery);
nestedQuery.setScoreMode(ScoreMode.None);
searchQuery.setQuery(nestedQuery);
//searchQuery.setGetTotalCount(true);// Atur parameter GetTotalCount ke true untuk mengembalikan jumlah total baris yang cocok.
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Anda dapat mengonfigurasi parameter columnsToGet untuk menentukan kolom yang akan dikembalikan atau menentukan bahwa semua kolom dikembalikan. Jika Anda tidak mengonfigurasi parameter ini, hanya kolom kunci utama yang dikembalikan.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Tentukan bahwa semua kolom dikembalikan.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Tentukan kolom yang ingin Anda kembalikan.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Tentukan bahwa jumlah total baris yang cocok bukan jumlah baris yang dikembalikan yang ditampilkan.
System.out.println("Row: " + resp.getRows());
}
Gabungkan kueri bersarang dengan kueri Boolean
Persyaratan kueri
Dalam contoh ini, tabel data terdiri dari kolom col_string tipe String dan kolom col_nested tipe String. Kolom col_nested menyimpan data dalam format JSON. Tabel berikut menjelaskan baris sampel dalam tabel data.
Catatan Untuk membantu Anda lebih memahami demonstrasi, nomor seri ditambahkan ke setiap baris.
Nomor seri | col_string | col_nested |
1 | a | [{"col_keyword": "tablestore"},{"col_keyword": "searchindex","col_long": 1}] |
2 | b | [{"col_keyword": "tablestore","col_long": 1}] |
3 | c | [{"col_keyword": "searchindex"},{"col_long": 1}] |
Sebagai contoh, Anda memiliki persyaratan kueri berikut untuk kolom col_nested:
Baris Anak yang Sama Memenuhi Beberapa Kondisi Kueri
Sebagai contoh, Anda ingin mengkueri baris di mana nilai kolom col_keyword adalah "tablestore" dan nilai kolom col_long tidak kosong. Kolom col_keyword dan col_long termasuk dalam baris anak yang sama dari kolom col_nested.
Baris Anak yang Berbeda Memenuhi Beberapa Kondisi Kueri
Sebagai contoh, Anda ingin mengkueri baris di mana nilai kolom col_keyword adalah "tablestore" dan nilai kolom col_long tidak kosong. Kolom col_keyword dan col_long termasuk dalam baris anak yang sama atau berbeda dari kolom col_nested.
Untuk mengkueri baris yang memenuhi persyaratan sebelumnya, lakukan langkah-langkah berikut:
Buat indeks pencarian untuk tabel data dan atur tipe kolom col_nested dalam indeks pencarian ke Nested.
Kolom col_nested terdiri dari subbidang berikut: subbidang col_keyword tipe Keyword dan subbidang col_long tipe Long.
Pilih metode kueri yang sesuai berdasarkan persyaratan kueri.
Jika Anda ingin memenuhi persyaratan kueri bahwa baris anak yang sama memenuhi beberapa kondisi kueri, Anda dapat menentukan beberapa kueri Boolean dalam kueri bersarang.
Jika Anda ingin memenuhi persyaratan bahwa baris anak yang berbeda memenuhi beberapa kondisi kueri, Anda dapat menentukan beberapa kueri bersarang dalam kueri Boolean.
Kode sampel berikut memberikan contoh cara mengkueri data berdasarkan persyaratan kueri Anda. Lihat kode sampel yang sesuai berdasarkan persyaratan kueri Anda.
Baris anak yang sama memenuhi beberapa kondisi kueri
Kode sampel berikut memberikan contoh cara mengkueri baris di mana nilai kolom col_nested.col_keyword adalah "tablestore" dan nilai kolom col_nested.col_long tidak kosong. Kolom col_nested.col_keyword dan col_nested.col_long termasuk dalam baris anak yang sama.
Berdasarkan baris sampel dalam tabel data, hanya baris dengan nomor seri 2 yang memenuhi kondisi kueri.
public static void nestedQuery(SyncClient client) {
// Kondisi kueri 1: Nilai kolom col_keyword di baris anak dari kolom col_nested adalah "tablestore".
TermQuery termQuery = new TermQuery();
termQuery.setFieldName("col_nested.col_keyword");
termQuery.setTerm(ColumnValue.fromString("tablestore"));
// Kondisi kueri 2: Nilai kolom col_long di baris anak dari kolom col_nested tidak kosong.
ExistsQuery existsQuery = new ExistsQuery();
existsQuery.setFieldName("col_nested.col_long");
// Gunakan operator And dari kueri Boolean untuk mengkueri baris yang memenuhi kedua kondisi kueri sebelumnya pada saat yang sama.
List<Query> mustQueries = new ArrayList<>();
mustQueries.add(termQuery);
mustQueries.add(existsQuery);
BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
// Tentukan beberapa kueri Boolean dalam kueri bersarang untuk mengkueri baris yang memenuhi kedua kondisi kueri sebelumnya pada saat yang sama.
NestedQuery nestedQuery = new NestedQuery(); // Atur tipe kueri ke NestedQuery.
nestedQuery.setPath("col_nested"); // Tentukan jalur kolom bersarang, yaitu jalur induk kolom yang ingin Anda kueri.
nestedQuery.setQuery(boolQuery);
nestedQuery.setScoreMode(ScoreMode.None);
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(nestedQuery);
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Anda dapat mengonfigurasi parameter columnsToGet untuk menentukan kolom yang akan dikembalikan atau menentukan bahwa semua kolom dikembalikan. Jika Anda tidak mengonfigurasi parameter ini, hanya kolom kunci utama yang dikembalikan.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Tentukan bahwa semua kolom dikembalikan.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Tentukan kolom yang ingin Anda kembalikan.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Tentukan bahwa jumlah total baris yang cocok bukan jumlah baris yang dikembalikan yang ditampilkan.
System.out.println("Row: " + resp.getRows());
}
Baris anak yang berbeda memenuhi beberapa kondisi kueri
Kode sampel berikut memberikan contoh cara mengkueri baris di mana nilai kolom col_nested.col_keyword adalah "tablestore" dan nilai kolom col_nested.col_long tidak kosong. Kolom col_nested.col_keyword dan col_nested.col_long termasuk dalam baris anak yang sama atau berbeda.
Berdasarkan baris sampel dalam tabel data, baris dengan nomor seri 1 dan 2 memenuhi kondisi kueri.
public static void nestedQuery(SyncClient client) {
// Kondisi kueri 1: Nilai kolom col_keyword di baris anak dari kolom col_nested adalah "tablestore".
TermQuery termQuery = new TermQuery();
termQuery.setFieldName("col_nested.col_keyword");
termQuery.setTerm(ColumnValue.fromString("tablestore"));
NestedQuery nestedTermQuery = new NestedQuery();
nestedTermQuery.setPath("col_nested");
nestedTermQuery.setScoreMode(ScoreMode.None);
nestedTermQuery.setQuery(termQuery);
// Kondisi kueri 2: Nilai kolom col_long di baris anak dari kolom col_nested tidak kosong.
ExistsQuery existsQuery = new ExistsQuery();
existsQuery.setFieldName("col_nested.col_long");
NestedQuery nestedExistsQuery = new NestedQuery();
nestedExistsQuery.setPath("col_nested");
nestedExistsQuery.setScoreMode(ScoreMode.None);
nestedExistsQuery.setQuery(existsQuery);
// Gunakan operator And dari kueri Boolean untuk mengkueri baris yang memenuhi kedua kondisi kueri sebelumnya.
List<Query> mustQueries = new ArrayList<>();
mustQueries.add(nestedTermQuery);
mustQueries.add(nestedExistsQuery);
// Tentukan beberapa kueri bersarang dalam kueri Boolean untuk mengkueri baris yang memenuhi kondisi kueri.
BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(boolQuery);
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
// Anda dapat mengonfigurasi parameter columnsToGet untuk menentukan kolom yang akan dikembalikan atau menentukan bahwa semua kolom dikembalikan. Jika Anda tidak mengonfigurasi parameter ini, hanya kolom kunci utama yang dikembalikan.
//SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
//columnsToGet.setReturnAll(true); // Tentukan bahwa semua kolom dikembalikan.
//columnsToGet.setColumns(Arrays.asList("ColName1","ColName2")); // Tentukan kolom yang ingin Anda kembalikan.
//searchRequest.setColumnsToGet(columnsToGet);
SearchResponse resp = client.search(searchRequest);
//System.out.println("TotalCount: " + resp.getTotalCount()); // Tentukan bahwa jumlah total baris yang cocok bukan jumlah baris yang dikembalikan yang ditampilkan.
System.out.println("Row: " + resp.getRows());
}
Gunakan fitur sorotan dalam kueri bersarang
Kode sampel berikut memberikan contoh cara menggunakan kueri bersarang untuk mengkueri baris di mana nilai subkolom Level1_Col1_Nested dari kolom bersarang bernama Col_Nested cocok dengan hangzhou shanghai dan menyoroti string kueri dalam hasil kueri.
/**
* Aktifkan fitur sorotan dengan menggunakan parameter innerHits untuk kueri bersarang.
*/
public static void nestedQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<TABLE_NAME>")
.indexName("<SEARCH_INDEX_NAME>")
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.nested()
.path("Col_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.match("Col_Nested.Level1_Col1_Nested", "hangzhou shanghai"))
.innerHits(InnerHits.newBuilder()
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col1_Nested", HighlightParameter.newBuilder().build())
.build())
.build()))
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// Tampilkan hasil yang disorot.
printSearchHit(resp.getSearchHits(), "");
}
/**
* Tampilkan konten yang memenuhi kondisi kueri.
* @param searchHits searchHits
* Jika output menggunakan struktur Nested @param prefix, tambahkan awalan untuk menampilkan informasi hierarki.
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s Skor: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s Baris: %s\n", prefix, searchHit.getRow().toString());
}
// Tampilkan segmen teks yang disorot dari kolom di setiap baris.
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s Sorotan: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
// Hasil sorotan dari kolom bersarang.
for (SearchInnerHit searchInnerHit : searchHit.getSearchInnerHits().values()) {
System.out.printf("%s Jalur: %s\n", prefix, searchInnerHit.getPath());
System.out.printf("%s InnerHit: \n", prefix);
printSearchHit(searchInnerHit.getSubSearchHits(), prefix + " ");
}
System.out.println();
}
}
Sebagai contoh, bidang Col_Nested terdiri dari subbidang berikut: subbidang Level1_Col1_Text tipe Text dan subbidang Level1_Col2_Nested tipe Nested. Subbidang Level1_Col2_Nested tipe Nested juga terdiri dari bidang Level2_Col1_Text.
Kode sampel berikut memberikan contoh cara menambahkan kueri Boolean ke kueri bersarang untuk menyoroti string kueri dalam bidang Level1_Col1_Text dan subbidang Level2_Col1_Text dari bidang Level1_Col2_Nested.
public static void nestedQueryWithHighlighting(SyncClient client) {
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<TABLE_NAME>")
.indexName("<SEARCH_INDEX_NAME>")
.returnAllColumnsFromIndex(true)
.searchQuery(SearchQuery.newBuilder()
.limit(5)
.query(QueryBuilders.nested()
.path("Col_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.bool()
.should(QueryBuilders.match("Col_Nested.Level1_Col1_Text", "hangzhou shanghai"))
.should(QueryBuilders.nested()
.path("Col_Nested.Level1_Col2_Nested")
.scoreMode(ScoreMode.Min)
.query(QueryBuilders.match("Col_Nested.Level1_Col2_Nested.Level2_Col1_Text", "hangzhou shanghai"))
.innerHits(InnerHits.newBuilder()
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col2_Nested.Level2_Col1_Text", HighlightParame
.build())
.build())))
.innerHits(InnerHits.newBuilder()
.sort(new Sort(Arrays.asList(
new ScoreSort(),
new DocSort()
)))
.highlight(Highlight.newBuilder()
.addFieldHighlightParam("Col_Nested.Level1_Col1_Text", HighlightParameter.newBuilder().build())
.build())
.build()))
.build())
.build();
SearchResponse resp = client.search(searchRequest);
// Tampilkan hasil yang disorot.
printSearchHit(resp.getSearchHits(), "");
}
/**
* Tampilkan konten yang memenuhi kondisi kueri.
* @param searchHits searchHits
* Jika output menggunakan struktur Nested @param prefix, tambahkan awalan untuk menampilkan informasi hierarki.
*/
private static void printSearchHit(List<SearchHit> searchHits, String prefix) {
for (SearchHit searchHit : searchHits) {
if (searchHit.getScore() != null) {
System.out.printf("%s Skor: %s\n", prefix, searchHit.getScore());
}
if (searchHit.getOffset() != null) {
System.out.printf("%s Offset: %s\n", prefix, searchHit.getOffset());
}
if (searchHit.getRow() != null) {
System.out.printf("%s Baris: %s\n", prefix, searchHit.getRow().toString());
}
// Tampilkan segmen teks yang disorot dari bidang di setiap baris.
if (searchHit.getHighlightResultItem() != null) {
System.out.printf("%s Sorotan: \n", prefix);
StringBuilder strBuilder = new StringBuilder();
for (Map.Entry<String, HighlightField> entry : searchHit.getHighlightResultItem().getHighlightFields().entrySet()) {
strBuilder.append(entry.getKey()).append(":").append("[");
strBuilder.append(StringUtils.join(",", entry.getValue().getFragments())).append("]\n");
}
System.out.printf("%s %s", prefix, strBuilder);
}
// Hasil sorotan dari kolom bersarang.
for (SearchInnerHit searchInnerHit : searchHit.getSearchInnerHits().values()) {
System.out.printf("%s Jalur: %s\n", prefix, searchInnerHit.getPath());
System.out.printf("%s InnerHit: \n", prefix);
printSearchHit(searchInnerHit.getSubSearchHits(), prefix + " ");
}
System.out.println();
}
}