Indeks pencarian mendukung tipe bidang JSON. Petakan kolom String dalam tabel data ke bidang JSON dalam indeks pencarian untuk melakukan pencarian terstruktur dan analitik pada data semi-terstruktur. Tipe bidang JSON menyediakan dua mode penyimpanan: Object dan Nested, yang masing-masing cocok untuk kueri bidang independen dan kueri objek bersarang berkorelasi.
Cara kerja
Saat Anda memetakan kolom String ke bidang JSON dalam indeks pencarian, Tablestore mengurai struktur JSON dan mengindeks sub-bidang individual untuk kueri. Tersedia dua mode penyimpanan — Object dan Nested — masing-masing dioptimalkan untuk pola kueri yang berbeda.
Object: Meratakan struktur bersarang menjadi bidang tingkat atas. Paling cocok untuk kueri bidang sederhana yang memerlukan performa tinggi.
Nested: Mempertahankan independensi dan asosiasi antar bidang dalam setiap objek bersarang. Paling cocok untuk kueri yang memerlukan pencocokan eksak dalam satu objek bersarang.
Perbedaan utama
|
Dimensi |
Object |
Nested |
|
Pemrosesan data |
Meratakan data bersarang menjadi bidang tingkat atas |
Menyimpan setiap objek bersarang sebagai dokumen independen |
|
Metode kueri |
Kueri standar |
Diperlukan NestedQuery |
|
Korelasi bidang |
Memungkinkan pencocokan silang antar bidang dari objek bersarang berbeda |
Mencocokkan bidang hanya dalam objek bersarang yang sama |
|
Performa |
Konsumsi resource lebih rendah |
Konsumsi resource lebih tinggi; mendukung kueri bidang berkorelasi |
Panduan pemilihan
Pilih Nested ketika kueri harus secara ketat mempertahankan korelasi antar bidang dalam objek bersarang. Pilih Object ketika prioritas utama adalah performa kueri tinggi dan korelasi bidang ketat tidak diperlukan.
Konfigurasi dan gunakan indeks bidang JSON
Buat indeks pencarian untuk bidang JSON dalam tiga langkah: pilih tipe JSON, konfigurasikan indeks, dan jalankan kueri.
Baik Anda memilih Object atau Nested, definisikan secara eksplisit tipe bidang untuk setiap sub-bidang. Sub-bidang tanpa tipe yang ditentukan akan diabaikan oleh indeks dan tidak dapat berpartisipasi dalam kueri.
Langkah 1: Pilih tipe JSON dan format data
Bagian berikut membandingkan tipe Object dan Nested, menunjukkan format data yang didukung, serta mendemonstrasikan cara menulis data JSON.
Pemilihan tipe JSON
Object: Paling cocok untuk kueri bidang independen. Memberikan performa kueri tinggi dengan konsumsi sumber daya rendah.
Nested: Paling cocok untuk kueri yang memerlukan korelasi antar bidang. Menjamin hasil akurat dalam setiap objek bersarang.
Hybrid: Tipe Object dan Nested dapat dikombinasikan dalam indeks yang sama untuk memenuhi kebutuhan kompleks.
Format data
Bidang JSON mendukung format array maupun non-array. Pilih format berdasarkan struktur data Anda:
// Format array
[{ "country": "China", "city": "Hangzhou" }, { "country": "USA", "city": "Seattle" }]
// Format non-array
{ "country": "China", "city": "Hangzhou" }
Tulis data
private static void putRow(SyncClient client) {
// Bangun primary key.
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("10001"));
PrimaryKey primaryKey = primaryKeyBuilder.build();
// Tentukan nama tabel.
RowPutChange rowPutChange = new RowPutChange("<TABLE_NAME>", primaryKey);
// Bangun data JSON mentah.
List<Map<String, Object>> addresses = Arrays.asList(
new HashMap<String, Object>() {{ put("country", "China"); put("city", "Hangzhou"); }},
new HashMap<String, Object>() {{ put("country", "USA"); put("city", "Seattle"); }}
);
String jsonString = JSON.toJSONString(addresses);
rowPutChange.addColumn(new Column("address", ColumnValue.fromString(jsonString)));
client.putRow(new PutRowRequest(rowPutChange));
}
Langkah 2: Konfigurasi struktur bidang dan buat indeks
Contoh berikut mengonfigurasi bidang JSON tingkat tunggal dengan dua sub-bidang. Definisikan tipe bidang dan properti untuk setiap sub-bidang agar dapat dikueri.
List<FieldSchema> subFieldSchemas = new ArrayList<FieldSchema>();
subFieldSchemas.add(new FieldSchema("country", FieldType.KEYWORD)
.setIndex(true).setEnableSortAndAgg(true));
subFieldSchemas.add(new FieldSchema("city", FieldType.KEYWORD)
.setIndex(true).setEnableSortAndAgg(true));
FieldSchema jsonFieldSchema = new FieldSchema("address", FieldType.Json)
.setJsonType(JsonType.OBJECT) // Setel ke JsonType.OBJECT atau JsonType.NESTED
.setSubFieldSchemas(subFieldSchemas);
Langkah 3: Kueri data
Object: Meratakan data bersarang. Akses bidang dengan menggabungkan nama bidang induk dan anak menggunakan titik (
.). Karena bidang diratakan, nilai dari objek bersarang berbeda dapat saling mencocokkan.Nested: Mempertahankan independensi setiap objek bersarang. Bungkus kondisi kueri dalam NestedQuery untuk memastikan pencocokan bidang hanya terjadi dalam objek bersarang yang sama.
Format terindeks
Asumsikan bidang address berisi data berikut: [{ "country": "China", "city": "Hangzhou" }, { "country": "USA", "city": "Seattle" }].
Format terindeks Object:
{"address.country": ["China", "USA"], "address.city": ["Hangzhou","Seattle"]}Format terindeks Nested: Dokumen independen
{ "country": "China", "city": "Hangzhou" }dan{ "country": "USA", "city": "Seattle" }
Dengan kondisi address.country ="China" DAN address.city="Seattle": Object cocok (nilai bidang lintas objek digabungkan), tetapi Nested tidak cocok (tidak ada satu objek pun yang memiliki keduanya). Dengan kondisi address.country ="China" DAN address.city="Hangzhou": kedua tipe cocok.
Contoh kueri
Contoh kueri tipe JSON Nested
Contoh berikut mengkueri baris di mana objek bersarang yang sama dari bidang `address` memenuhi dua kondisi: address.country adalah "China" dan address.city adalah "Seattle".
public static void nestedQuery(SyncClient client) {
// Kondisi 1: Nilai bidang country dalam sub-baris address harus "China".
TermQuery termQuery1 = new TermQuery();
termQuery1.setFieldName("address.country");
termQuery1.setTerm(ColumnValue.fromString("China"));
// Kondisi 2: Nilai bidang city dalam sub-baris address harus "Seattle".
TermQuery termQuery2 = new TermQuery();
termQuery2.setFieldName("address.city");
termQuery2.setTerm(ColumnValue.fromString("Seattle"));
// Gunakan kondisi AND dari BoolQuery untuk mengkueri sub-baris yang memenuhi kedua kondisi.
List<Query> mustQueries = new ArrayList<>();
mustQueries.add(termQuery1);
mustQueries.add(termQuery2);
BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
// Setel BoolQuery dalam NestedQuery untuk mewajibkan satu sub-baris memenuhi beberapa kondisi kueri sekaligus.
NestedQuery nestedQuery = new NestedQuery(); // Setel tipe kueri ke NestedQuery.
nestedQuery.setPath("address"); // Setel path kolom tipe nested, yaitu path induk dari bidang yang akan dikueri.
nestedQuery.setQuery(boolQuery);
nestedQuery.setScoreMode(ScoreMode.None);
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(nestedQuery);
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
SearchResponse resp = client.search(searchRequest);
System.out.println("Row: " + resp.getRows());
}
Contoh kueri tipe JSON Object
Contoh berikut mengkueri baris di mana bidang `address` memenuhi dua kondisi lintas objek bersarangnya: address.country adalah "China" dan address.city adalah "Seattle".
public static void boolQuery(SyncClient client) {
// Kondisi 1: Nilai bidang country dalam sub-baris address harus "China".
TermQuery termQuery1 = new TermQuery();
termQuery1.setFieldName("address.country");
termQuery1.setTerm(ColumnValue.fromString("China"));
// Kondisi 2: Nilai bidang city dalam sub-baris address harus "Seattle".
TermQuery termQuery2 = new TermQuery();
termQuery2.setFieldName("address.city");
termQuery2.setTerm(ColumnValue.fromString("Seattle"));
// Gunakan kondisi AND dari BoolQuery untuk mengkueri sub-baris yang memenuhi kedua kondisi.
List<Query> mustQueries = new ArrayList<>();
mustQueries.add(termQuery1);
mustQueries.add(termQuery2);
BoolQuery boolQuery = new BoolQuery();
boolQuery.setMustQueries(mustQueries);
SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(boolQuery);
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
SearchResponse resp = client.search(searchRequest);
System.out.println("Row: " + resp.getRows());
}
Contoh JSON
Konfigurasi skema untuk bidang JSON tingkat tunggal dan multi-level mengikuti struktur yang sama, baik untuk Object maupun Nested, dengan perbedaan hanya pada pengaturan tipe.
JSON tingkat tunggal
Contoh Java berikut membuat bidang JSON tingkat tunggal tags (pilih tipe JSON sesuai kebutuhan Anda) dengan tiga sub-bidang:
tagName: Tipe Keyword. Digunakan untuk pencocokan eksak dan agregasi nama tag.
score: Tipe Double. Digunakan untuk perhitungan numerik dan pengurutan bobot tag.
time: Tipe Date dalam format epoch_millis. Digunakan untuk kueri rentang waktu dan analisis deret waktu.
Format array dan non-array didukung untuk penulisan data:
// Format array
[{"tagName":"tag1", "score":0.8,"time": 1730690237000 }, {"tagName":"tag2", "score":0.2,"time": 1730691557000}]
// Format non-array
{"tagName":"tag1", "score":0.8,"time": 1730690237000 }
Konfigurasi skema lengkap:
List<FieldSchema> subFieldSchemas = new ArrayList<FieldSchema>();
subFieldSchemas.add(new FieldSchema("tagName", FieldType.KEYWORD)
.setIndex(true).setEnableSortAndAgg(true));
subFieldSchemas.add(new FieldSchema("score", FieldType.DOUBLE)
.setIndex(true).setEnableSortAndAgg(true));
subFieldSchemas.add(new FieldSchema("time", FieldType.DATE)
.setDateFormats(Arrays.asList("epoch_millis")));
FieldSchema nestedFieldSchema = new FieldSchema("tags", FieldType.Json)
.setJsonType(JsonType.OBJECT) // Ganti dengan JsonType.NESTED jika diperlukan
.setSubFieldSchemas(subFieldSchemas);
JSON multi-level
Contoh Java berikut membuat bidang JSON multi-level user (pilih tipe JSON sesuai kebutuhan Anda) yang mencakup informasi pengguna dasar dan data alamat bersarang. Bidang JSON multi-level mendukung kombinasi tipe Nested dan Object.
Bidang dasar: name (Keyword, untuk kueri nama eksak), age (Long, untuk filter rentang usia), birth (Date, format yyyy-MM-dd HH:mm:ss.SSS, untuk kueri tanggal lahir), phone (Keyword, untuk pencocokan kontak).
Bidang bersarang:
address(pilih tipe JSON sesuai kebutuhan Anda), berisiprovince,city, danstreet(semuanya tipe Keyword) untuk kueri lokasi hirarkis.
Data pengguna contoh:
{
"name": "John",
"age": 20,
"birth": "2014-10-10 12:00:00.000",
"phone": "1390000****",
"address": {
"province": "Zhejiang",
"city": "Hangzhou",
"street": "1201, Sunshine Community, Yangguang Avenue"
}
}
Konfigurasi skema lengkap untuk JSON multi-level:
// Skema sub-bidang untuk address (path: user.address)
List<FieldSchema> addressSubFiledSchemas = new ArrayList<>();
addressSubFiledSchemas.add(new FieldSchema("province",FieldType.KEYWORD));
addressSubFiledSchemas.add(new FieldSchema("city",FieldType.KEYWORD));
addressSubFiledSchemas.add(new FieldSchema("street",FieldType.KEYWORD));
// Skema sub-bidang untuk user (path: user)
List<FieldSchema> subFieldSchemas = new ArrayList<>();
subFieldSchemas.add(new FieldSchema("name",FieldType.KEYWORD));
subFieldSchemas.add(new FieldSchema("age",FieldType.LONG));
subFieldSchemas.add(new FieldSchema("birth",FieldType.DATE)
.setDateFormats(Arrays.asList("yyyy-MM-dd HH:mm:ss.SSS")));
subFieldSchemas.add(new FieldSchema("phone",FieldType.KEYWORD));
subFieldSchemas.add(new FieldSchema("address",FieldType.JSON)
.setJsonType(JsonType.NESTED) // Ganti dengan JsonType.OBJECT jika diperlukan
.setSubFieldSchemas(addressSubFiledSchemas));
// Buat bidang induk: user
List<FieldSchema> fieldSchemas = new ArrayList<>();
fieldSchemas.add(new FieldSchema("user",FieldType.JSON)
.setJsonType(JsonType.OBJECT) // Ganti dengan JsonType.NESTED jika diperlukan
.setSubFieldSchemas(subFieldSchemas));
Batasan
Bidang vektor: Bidang vektor tidak dapat digunakan sebagai sub-bidang bidang JSON. Konfigurasikan indeks bidang vektor secara terpisah.
Tipe Nested: Bidang JSON Nested tidak mendukung pre-sorting indeks. Gunakan NestedQuery untuk mengkueri bidang bersarang.
Sub-bidang array: Untuk sub-bidang non-JSON yang berisi data berformat array, atur properti IsArray ke true. Tulis data dalam format array standar
`"[a, b, c]"`. Jika tidak, indeks tidak dapat menyinkronkan atau mengkueri sub-bidang tersebut.
Referensi
Tipe bidang JSON saat ini didukung melalui Tablestore SDK for Java, Tablestore SDK for Go, dan Tablestore SDK for Python.