Ikhtisar Bidang JSON
Ketika membangun aplikasi seperti katalog produk, sistem manajemen konten, atau mesin preferensi pengguna, Anda sering kali perlu menyimpan metadata yang fleksibel di samping penyematan vektor. Atribut produk bervariasi berdasarkan kategori, preferensi pengguna berkembang dari waktu ke waktu, dan properti dokumen memiliki struktur bersarang yang kompleks. Bidang JSON di Milvus mengatasi tantangan ini dengan memungkinkan Anda menyimpan dan meminta data terstruktur yang fleksibel tanpa mengorbankan kinerja.
Apa yang dimaksud dengan bidang JSON?
Bidang JSON adalah tipe data yang ditentukan skema (DataType.JSON) di Milvus yang menyimpan data nilai-kunci terstruktur. Tidak seperti kolom basis data tradisional yang kaku, field JSON mengakomodasi objek bersarang, array, dan tipe data campuran sambil menyediakan beberapa opsi pengindeksan untuk kueri cepat.
Contoh struktur bidang JSON:
{
"metadata": {
"category": "electronics",
"brand": "BrandA",
"in_stock": true,
"price": 99.99,
"string_price": "99.99",
"tags": ["clearance", "summer_sale"],
"supplier": {
"name": "SupplierX",
"country": "USA",
"contact": {
"email": "support@supplierx.com",
"phone": "+1-800-555-0199"
}
}
}
}
Dalam contoh ini, metadata adalah bidang JSON tunggal yang berisi campuran nilai datar (misalnya category, in_stock), larik (tags), dan objek bersarang (supplier).
Konvensi penamaan: Gunakan hanya huruf, angka, dan garis bawah pada kunci JSON. Hindari karakter khusus, spasi, atau titik karena dapat menyebabkan masalah penguraian dalam kueri.
Bidang JSON vs bidang dinamis
Hal yang sering membingungkan adalah perbedaan antara field JSON dan field dinamis. Meskipun keduanya terkait dengan JSON, keduanya memiliki tujuan yang berbeda.
Tabel di bawah ini merangkum perbedaan utama antara field JSON dan field dinamis:
Fitur |
Bidang JSON |
Bidang Dinamis |
|---|---|---|
Definisi skema |
Bidang skalar yang harus dideklarasikan secara eksplisit di dalam skema koleksi dengan tipe |
Bidang JSON tersembunyi (bernama |
Kasus penggunaan |
Menyimpan data terstruktur yang skemanya diketahui dan konsisten. |
Menyimpan data yang fleksibel, berkembang, atau semi-terstruktur yang tidak sesuai dengan skema tetap. |
Kontrol |
Anda mengontrol nama dan struktur bidang. |
Dikelola sistem untuk bidang yang tidak ditentukan. |
Kueri |
Kueri menggunakan nama bidang atau kunci target di dalam bidang JSON: |
Kueri secara langsung menggunakan kunci bidang dinamis: |
Operasi dasar
Alur kerja dasar untuk menggunakan bidang JSON melibatkan pendefinisiannya di dalam skema Anda, memasukkan data, dan kemudian melakukan kueri data dengan menggunakan ekspresi filter tertentu.
Mendefinisikan bidang JSON
Untuk menggunakan bidang JSON, tentukan secara eksplisit dalam skema koleksi Anda saat membuat koleksi. Contoh berikut ini menunjukkan cara membuat koleksi dengan bidang metadata bertipe DataType.JSON:
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530") # Replace with your server address
# Create schema
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True) # Primary field
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5) # Vector field
# Define a JSON field that allows null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)
client.create_collection(
collection_name="product_catalog",
schema=schema
)
Dalam contoh ini, bidang JSON yang ditetapkan dalam skema koleksi memungkinkan nilai null dengan nullable=True. Untuk detailnya, lihat Nullable & Default.
Menyisipkan data
Setelah koleksi dibuat, masukkan entitas yang berisi objek JSON terstruktur di bidang JSON yang Anda tentukan. Data Anda harus diformat sebagai daftar kamus.
entities = [
{
"product_id": 1,
"vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"metadata": { # JSON field
"category": "electronics",
"brand": "BrandA",
"in_stock": True,
"price": 99.99,
"string_price": "99.99",
"tags": ["clearance", "summer_sale"],
"supplier": {
"name": "SupplierX",
"country": "USA",
"contact": {
"email": "support@supplierx.com",
"phone": "+1-800-555-0199"
}
}
}
}
]
client.insert(collection_name="product_catalog", data=entities)
Operasi pemfilteran
Sebelum Anda dapat melakukan operasi pemfilteran pada bidang JSON, pastikan:
Anda telah membuat indeks pada setiap bidang vektor.
Koleksi dimuat ke dalam memori.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type="AUTOINDEX",
index_name="vector_index",
metric_type="COSINE"
)
client.create_index(collection_name="product_catalog", index_params=index_params)
client.load_collection(collection_name="product_catalog")
Setelah persyaratan ini terpenuhi, Anda dapat menggunakan ekspresi di bawah ini untuk memfilter koleksi Anda berdasarkan nilai di dalam bidang JSON. Ekspresi filter ini memanfaatkan sintaksis jalur JSON tertentu dan operator khusus.
Memfilter dengan sintaks jalur JSON
Untuk menanyakan kunci tertentu, gunakan notasi tanda kurung untuk mengakses kunci JSON: json_field_name["key"]. Untuk kunci bersarang, rangkai kunci-kunci tersebut menjadi satu: json_field_name["key1"]["key2"].
Untuk memfilter entitas di mana category adalah "electronics":
# Define filter expression
filter = 'metadata["category"] == "electronics"'
client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
Untuk memfilter entitas dengan kunci bersarang supplier["country"] adalah "USA":
# Define filter expression
filter = 'metadata["supplier"]["country"] == "USA"'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Memfilter dengan operator khusus JSON
Milvus juga menyediakan operator khusus untuk menanyakan nilai larik pada kunci bidang JSON tertentu. Sebagai contoh:
json_contains(identifier, expr): Memeriksa apakah elemen atau sub-larik tertentu ada di dalam larik JSONjson_contains_all(identifier, expr): Memastikan bahwa semua elemen dari ekspresi JSON yang ditentukan ada di dalam fieldjson_contains_any(identifier, expr): Memfilter entitas yang setidaknya memiliki satu anggota ekspresi JSON di dalam field
Untuk menemukan produk yang memiliki nilai "summer_sale" di bawah kunci tags:
# Define filter expression
filter = 'json_contains(metadata["tags"], "summer_sale")'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Untuk menemukan produk yang memiliki setidaknya satu dari nilai "electronics", "new", atau "clearance" di bawah kunci tags:
# Define filter expression
filter = 'json_contains_any(metadata["tags"], ["electronics", "new", "clearance"])'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Untuk informasi lebih lanjut tentang operator khusus JSON, lihat Operator JSON.
Berikutnya: Mempercepat kueri JSON
Secara default, kueri pada bidang JSON tanpa akselerasi akan melakukan pemindaian penuh terhadap semua baris, yang dapat berjalan lambat pada kumpulan data yang besar. Untuk mempercepat kueri JSON, Milvus menyediakan fitur pengindeksan dan pengoptimalan penyimpanan tingkat lanjut.
Tabel di bawah ini merangkum perbedaan dan skenario penggunaan terbaiknya:
Teknik |
Terbaik Untuk |
Akselerasi Larik |
Catatan |
|---|---|---|---|
Pengindeksan JSON |
Kumpulan kecil kunci yang sering diakses, larik pada kunci larik tertentu |
Ya (pada kunci larik yang diindeks) |
Harus memilih kunci terlebih dahulu, diperlukan pemeliharaan jika skema berkembang |
Penghancuran JSON |
Percepatan umum di banyak kunci, fleksibel untuk beragam kueri |
Tidak (tidak mempercepat nilai di dalam larik) |
Konfigurasi penyimpanan ekstra, larik masih membutuhkan indeks per kunci |
Indeks NGRAM |
Pencarian wildcard, pencocokan substring dalam bidang teks |
N/A |
Tidak untuk filter numerik/rentang |
Tips: Anda dapat menggabungkan pendekatan-pendekatan ini-misalnya, menggunakan penghancuran JSON untuk akselerasi kueri yang luas, pengindeksan JSON untuk kunci larik berfrekuensi tinggi, dan pengindeksan NGRAM untuk penelusuran teks yang fleksibel.
Untuk detail implementasi, lihat:
PERTANYAAN UMUM
Apakah ada batasan pada ukuran bidang JSON?
Ya. Setiap bidang JSON dibatasi hingga 65.536 byte.
Apakah bidang JSON mendukung pengaturan nilai default?
Tidak, bidang JSON tidak mendukung nilai default. Namun, Anda dapat mengatur nullable=True saat mendefinisikan bidang untuk mengizinkan entri kosong.
Lihat Nullable & Default untuk detailnya.
Apakah ada konvensi penamaan untuk kunci bidang JSON?
Ya, untuk memastikan kompatibilitas dengan kueri dan pengindeksan:
Gunakan hanya huruf, angka, dan garis bawah pada kunci JSON.
Hindari penggunaan karakter khusus, spasi, atau titik (
.,/, dll.).Kunci yang tidak kompatibel dapat menyebabkan masalah penguraian dalam ekspresi filter.
Bagaimana Milvus menangani nilai string dalam bidang JSON?
Milvus menyimpan nilai string persis seperti yang muncul di input JSON-tanpa transformasi semantik. String yang dikutip dengan tidak benar dapat mengakibatkan kesalahan selama penguraian.
Contoh string yang valid:
"a\"b", "a'b", "a\\b"
Contoh string yang tidak valid:
'a"b', 'a\'b'