Saat mengkueri data menggunakan search index, Anda dapat menentukan urutan pengurutan sebelumnya atau menentukannya saat kueri untuk mengambil hasil dalam urutan tertentu. Jika set hasil berukuran besar, Anda dapat menggunakan lamanisasi berbasis offset atau berbasis token untuk dengan cepat menemukan data yang dibutuhkan.
Index sort
Secara default, search index mengurutkan data berdasarkan index sort-nya. Saat Anda mengkueri data dengan search index, pengaturan IndexSort ini menentukan urutan pengurutan default.
Saat membuat search index, Anda dapat menentukan IndexSort kustom. Jika tidak ditentukan, search index secara default mengurutkan berdasarkan primary key.
Index sort hanya mendukung
PrimaryKeySort(urut berdasarkan primary key) danFieldSort(urut berdasarkan nilai bidang).Search index yang memiliki bidang bertipe nested tidak mendukung index sort.
Sort at query time
Anda hanya dapat mengurutkan berdasarkan bidang yang memiliki enableSortAndAgg diatur ke true.
Anda dapat menentukan urutan pengurutan untuk setiap kueri. Search index mendukung empat jenis sorter (Sorter) berikut. Anda juga dapat menggabungkan beberapa sorter untuk membuat pengurutan multi-level.
ScoreSort
Mengurutkan hasil berdasarkan skor relevansinya, yang dihitung menggunakan algoritma BM25. Ini cocok untuk skenario seperti pencarian teks lengkap.
Jika Anda perlu mengurutkan hasil berdasarkan skor relevansi, Anda harus secara eksplisit menentukan ScoreSort. Jika tidak, hasil akan diurutkan berdasarkan konfigurasi IndexSort dari search index.
SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new ScoreSort())));PrimaryKeySort
Mengurutkan hasil berdasarkan primary key.
SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new PrimaryKeySort()))); // Urutan ascending.
//searchQuery.setSort(new Sort(Arrays.asList(new PrimaryKeySort(SortOrder.DESC)))); // Urutan descending.FieldSort
Mengurutkan hasil berdasarkan nilai kolom tertentu.
Single-column sort
Mengurutkan hasil berdasarkan nilai dalam satu kolom.
SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new FieldSort("col", SortOrder.ASC))));Multi-column sort
Mengurutkan hasil berdasarkan nilai dalam satu kolom, lalu berdasarkan nilai dalam kolom lainnya.
SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(
new FieldSort("col1", SortOrder.ASC), new FieldSort("col2", SortOrder.ASC))));Fallback sort
Saat mengurutkan berdasarkan kolom bertipe Long, Double, atau Date, Anda dapat menggunakan parameter missingField untuk menentukan kolom cadangan dengan tipe yang sama. Kolom cadangan ini digunakan untuk baris apa pun yang tidak memiliki nilai pada kolom utama pengurutan.
/**
* Mengurutkan berdasarkan `Col_Long` dalam urutan descending. Jika suatu baris tidak memiliki nilai `Col_Long`, maka menggunakan nilai dari `Col_Long_sec` sebagai gantinya.
*/
SearchQuery searchQuery = new SearchQuery();
FieldSort fieldSort = new FieldSort("Col_Long");
// Menentukan `Col_Long_sec` sebagai fallback untuk nilai yang hilang di `Col_Long`.
fieldSort.setMissingField("Col_Long_sec");
fieldSort.setOrder(SortOrder.DESC); Missing value sort
Jika suatu dokumen tidak memiliki bidang pengurutan, Anda dapat menggunakan parameter missingValue untuk mengontrol posisinya dalam hasil yang diurutkan.
Perilaku pengurutan adalah sebagai berikut:
Ketika
missingValuediatur keFieldSort.FIRST_WHEN_MISSING, dokumen dengan nilai yang hilang selalu ditempatkan di awal hasil, terlepas dari urutan pengurutan (ascending atau descending).Ketika
missingValuediatur keFieldSort.LAST_WHEN_MISSINGatau tidak diatur (null), dokumen dengan nilai yang hilang selalu ditempatkan di akhir hasil, terlepas dari urutan pengurutan./** * Mengurutkan berdasarkan `Col_Long` dalam urutan descending. Menempatkan dokumen yang tidak memiliki nilai `Col_Long` di awal hasil. */ SearchQuery searchQuery = new SearchQuery(); FieldSort fieldSort = new FieldSort("Col_Long"); // Menempatkan dokumen dengan nilai yang hilang di awal. fieldSort.setMissingValue(FieldSort.FIRST_WHEN_MISSING); fieldSort.setOrder(SortOrder.DESC); searchQuery.setSort(new Sort(Arrays.asList(fieldSort)));
Multi-value sort
Untuk bidang bernilai ganda, seperti array atau bidang bertipe nested type, Anda dapat menggunakan parameter mode untuk menentukan nilai mana dalam koleksi yang digunakan untuk pengurutan.
Urutkan berdasarkan nilai tertentu dalam array.
// Baris doc1 dan doc2 memiliki bidang array bernama field1. Di doc1, nilai field1 adalah [2,3]. Di doc2, nilainya adalah [1,3,4].
// Anda dapat mengatur parameter mode untuk menentukan nilai mana dalam array yang digunakan untuk pengurutan.
{
// Jika mode diatur ke SortMode.MAX, hasilnya adalah doc2 (diurutkan berdasarkan 4) lalu doc1 (diurutkan berdasarkan 3).
FieldSort fieldSort = new FieldSort("field1", SortOrder.DESC);
fieldSort.setMode(SortMode.MAX);
}
{
// Jika mode diatur ke SortMode.MIN, hasilnya adalah doc1 (diurutkan berdasarkan 2) lalu doc2 (diurutkan berdasarkan 1).
FieldSort fieldSort = new FieldSort("field1", SortOrder.DESC);
fieldSort.setMode(SortMode.MIN);
}Anda juga dapat mengurutkan berdasarkan nilai dalam sub-bidang bertipe nested.
// Baris doc1 dan doc2 memiliki bidang bertipe nested bernama field1.
// Di doc1, nilai field1 adalah [{"name":"b", "age":1},{"name":"a", "age":7}].
// Di doc2, nilai field1 adalah [{"name":"a", "age":1},{"name":"c", "age":1},{"name":"d", "age":5}].
{
// Urutkan semua sub-baris dan gunakan parameter mode untuk menentukan nilai mana yang digunakan untuk pengurutan.
// Jika Anda mengatur mode ke SortMode.MAX dan mengurutkan berdasarkan bidang age, hasilnya adalah doc1 (diurutkan berdasarkan 7) lalu doc2 (diurutkan berdasarkan 5).
FieldSort fieldSort = new FieldSort("field1.age", SortOrder.DESC);
fieldSort.setMode(SortMode.MAX);
String path = "field1";
NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.matchAll().build());
fieldSort.setNestedFilter(nestedFilter);
}
{
// Urutkan hanya sub-baris di mana age=1 dan gunakan parameter mode untuk menentukan nilai mana yang digunakan untuk pengurutan.
{
// Jika Anda mengatur mode ke SortMode.MAX dan mengurutkan berdasarkan bidang name, hasilnya adalah doc2 (diurutkan berdasarkan "c") lalu doc1 (diurutkan berdasarkan "b").
FieldSort fieldSort = new FieldSort("field1.name", SortOrder.DESC);
fieldSort.setMode(SortMode.MAX);
String path = "field1";
NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.term("field1.age",1).build());
fieldSort.setNestedFilter(nestedFilter);
}
{
// Jika Anda mengatur mode ke SortMode.MIN dan mengurutkan berdasarkan bidang name, hasilnya adalah doc1 (diurutkan berdasarkan "b") lalu doc2 (diurutkan berdasarkan "a").
FieldSort fieldSort = new FieldSort("field1.name", SortOrder.DESC);
fieldSort.setMode(SortMode.MIN);
String path = "field1";
NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.term("field1.age",1).build());
fieldSort.setNestedFilter(nestedFilter);
}
}GeoDistanceSort
Mengurutkan hasil berdasarkan jarak dari titik geografis.
SearchQuery searchQuery = new SearchQuery();
// Mengurutkan hasil berdasarkan jarak dari nilai kolom `geo` (Geopoint) ke titik "0,0".
Sort.Sorter sorter = new GeoDistanceSort("geo", Arrays.asList("0, 0"));
searchQuery.setSort(new Sort(Arrays.asList(sorter)));Paging methods
Saat mengambil hasil, Anda dapat menggunakan parameter limit dan offset atau token untuk lamanisasi.
Limit and offset paging
Anda dapat menggunakan limit dan offset untuk paging, tetapi jumlah limit dan offset tidak boleh melebihi 100.000, dan nilai maksimum untuk limit adalah 100.
Untuk mempelajari cara meningkatkan limit hingga 1.000, lihat Bagaimana cara meningkatkan batas hasil kueri Search API menjadi 1.000 untuk search index?.
Jika tidak diatur, limit default-nya adalah 10 dan offset default-nya adalah 0.
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setLimit(100);
searchQuery.setOffset(100);Token-based paging
Kami merekomendasikan penggunaan lamanisasi berbasis token untuk deep paging karena tidak memiliki batasan kedalaman.
Jika kueri masih memiliki hasil tambahan untuk dikembalikan, respons akan menyertakan nextToken. Gunakan token ini dalam permintaan berikutnya untuk mengambil halaman hasil berikutnya.
Secara default, lamanisasi berbasis token hanya memungkinkan Anda bergerak maju melalui hasil. Namun, karena token tetap valid selama sesi lamanisasi, Anda dapat menyimpan cache token sebelumnya untuk menerapkan lamanisasi mundur.
Untuk menyimpan nextToken secara persisten atau mengirimkannya ke aplikasi front-end, Anda harus melakukan encode Base64 terhadapnya. nextToken merupakan array byte, bukan string. Mengonversinya langsung dengan new String(nextToken) akan merusak token dan menyebabkan kehilangan data.
Token mempertahankan urutan pengurutan dari permintaan sebelumnya, baik itu index sort default maupun urutan pengurutan kustom. Oleh karena itu, Anda tidak dapat menentukan parameter Sort dalam permintaan berbasis token. Anda juga tidak dapat menggunakan parameter offset, karena token itu sendiri yang menentukan posisi awal.
Search index yang memiliki bidang bertipe nested tidak mendukung index sort. Untuk paginate hasil dari search index semacam itu, Anda harus menentukan urutan pengurutan dalam kueri Anda. Jika tidak, server tidak akan mengembalikan nextToken meskipun masih tersedia hasil tambahan.
private static void readMoreRowsWithToken(SyncClient client) {
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setGetTotalCount(true);// Atur ke true untuk mengembalikan jumlah total baris yang sesuai.
// Tentukan nama tabel (misalnya, sampleTable) dan nama search index (misalnya, sampleSearchIndex). Anda dapat menemukan nama search index di tab Indexes tabel Anda di Konsol Tablestore atau dengan mencantumkan search index menggunakan SDK.
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
SearchResponse resp = client.search(searchRequest);
if (!resp.isAllSuccess()) {
throw new RuntimeException("not all success");
}
List<Row> rows = resp.getRows();
while (resp.getNextToken()!=null) { // nextToken null berarti semua data telah diambil.
// Dapatkan nextToken.
byte[] nextToken = resp.getNextToken();
{
// Jika Anda perlu menyimpan nextToken secara persisten atau mengirimkannya ke aplikasi front-end, gunakan encoding Base64 untuk mengonversinya ke string.
// Token itu sendiri bukan string. Mengonversinya langsung menggunakan new String(nextToken) akan merusak token.
String tokenAsString = Base64.toBase64String(nextToken);
// Dekode string kembali ke array byte.
byte[] tokenAsByte = Base64.fromBase64String(tokenAsString);
}
// Atur token untuk permintaan berikutnya.
searchRequest.getSearchQuery().setToken(nextToken);
resp = client.search(searchRequest);
if (!resp.isAllSuccess()) {
throw new RuntimeException("not all success");
}
rows.addAll(resp.getRows());
}
System.out.println("RowSize: " + rows.size());
System.out.println("TotalCount: " + resp.getTotalCount());// Mencetak jumlah total baris yang sesuai, bukan jumlah baris yang dikembalikan dalam respons ini.
}FAQ
References
Search index mendukung berbagai jenis kueri, termasuk Term query, Terms query, MatchAll query, Match query, MatchPhrase query, Prefix query, Range query, Wildcard query, Geo query, Vector query, Boolean query, Nested query, dan Exists query. Anda dapat memilih jenis kueri yang sesuai untuk pengambilan data multidimensi.
Untuk mengurutkan atau melamanisasi set hasil, gunakan fitur pengurutan dan lamanisasi. Untuk informasi lebih lanjut, lihat Urutkan dan lamanisasi hasil.
Untuk mengelompokkan set hasil berdasarkan kolom tertentu dan hanya mengembalikan satu dokumen untuk setiap kelompok, gunakan fitur collapsing. Untuk informasi lebih lanjut, lihat Collapsing.
Untuk analisis data, seperti menemukan nilai maksimum atau minimum, menghitung jumlah, atau menghitung baris, Anda dapat menggunakan fitur agregasi dari Search API atau kueri SQL. Untuk informasi lebih lanjut, lihat Agregasi dan Kueri SQL.
Untuk ekspor data cepat di mana urutan keseluruhan hasil tidak penting, Anda dapat menggunakan API ParallelScan dan ComputeSplits untuk mengekspor data secara paralel. Untuk informasi lebih lanjut, lihat Ekspor data secara paralel.