Bidang JSON
JSON (JavaScript Object Notation) adalah format pertukaran data ringan yang menyediakan cara yang fleksibel untuk menyimpan dan menanyakan struktur data yang kompleks. Di Milvus, Anda dapat menyimpan informasi terstruktur tambahan di samping data vektor menggunakan bidang JSON, sehingga memungkinkan pencarian dan kueri tingkat lanjut yang menggabungkan kemiripan vektor dengan pemfilteran terstruktur.
Bidang JSON ideal untuk aplikasi yang memerlukan metadata untuk mengoptimalkan hasil pencarian. Misalnya, dalam e-commerce, vektor produk dapat ditingkatkan dengan atribut seperti kategori, harga, dan merek. Dalam sistem rekomendasi, vektor pengguna dapat digabungkan dengan preferensi dan informasi demografis. Di bawah ini adalah contoh bidang JSON yang umum.
{
"category": "electronics",
"price": 99.99,
"brand": "BrandA"
}
Menambahkan bidang JSON
Untuk menggunakan bidang JSON di Milvus, tentukan jenis bidang yang relevan dalam skema koleksi, atur datatype
ke jenis JSON yang didukung, misalnya, JSON
.
Berikut ini cara mendefinisikan skema koleksi yang menyertakan bidang JSON.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema(
auto_id=False,
enable_dynamic_fields=True,
)
schema.add_field(field_name="metadata", datatype=DataType.JSON)
schema.add_field(field_name="pk", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=3)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
schema.addField(AddFieldReq.builder()
.fieldName("metadata")
.dataType(DataType.JSON)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("pk")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("embedding")
.dataType(DataType.FloatVector)
.dimension(3)
.build());
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const schema = [
{
name: "metadata",
data_type: DataType.JSON,
},
{
name: "pk",
data_type: DataType.Int64,
is_primary_key: true,
},
{
name: "embedding",
data_type: DataType.FloatVector,
dim: 3,
},
];
export jsonField='{
"fieldName": "metadata",
"dataType": "JSON"
}'
export pkField='{
"fieldName": "pk",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "embedding",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 3
}
}'
export schema="{
\"autoID\": false,
\"fields\": [
$jsonField,
$pkField,
$vectorField
]
}"
Dalam contoh ini, kita menambahkan bidang JSON bernama metadata
untuk menyimpan metadata tambahan yang terkait dengan data vektor, seperti kategori produk, harga, dan informasi merek.
Bidang utama dan bidang vektor wajib ada saat Anda membuat koleksi. Bidang utama mengidentifikasi setiap entitas secara unik, sedangkan bidang vektor sangat penting untuk pencarian kemiripan. Untuk lebih jelasnya, lihat Bidang Utama & AutoID, Vektor Padat, Vektor Biner, atau Vektor Jarang.
Membuat koleksi
Ketika membuat koleksi, Anda harus membuat indeks untuk bidang vektor untuk memastikan kinerja pengambilan. Dalam contoh ini, kami menggunakan AUTOINDEX
untuk menyederhanakan penyiapan indeks. Untuk lebih jelasnya, lihat AUTOINDEX.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX",
metric_type="COSINE"
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
.fieldName("embedding")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE)
.build());
const indexParams = {
index_name: 'embedding_index',
field_name: 'embedding',
metricType: MetricType.CONSINE,
index_type: IndexType.AUTOINDEX,
);
export indexParams='[
{
"fieldName": "embedding",
"metricType": "COSINE",
"indexType": "AUTOINDEX"
}
]'
Gunakan skema yang ditentukan dan parameter indeks untuk membuat koleksi.
client.create_collection(
collection_name="my_json_collection",
schema=schema,
index_params=index_params
)
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_json_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
client.create_collection({
collection_name: "my_json_collection",
schema: schema,
index_params: indexParams
})
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_json_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
Menyisipkan data
Setelah membuat koleksi, Anda dapat menyisipkan data yang menyertakan bidang JSON.
# Data to be inserted
data = [
{
"metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": {"category": "home_appliances", "price": 249.99, "brand": "BrandB"},
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
"metadata": {"category": "furniture", "price": 399.99, "brand": "BrandC"},
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
}
]
# Insert data into the collection
client.insert(
collection_name="your_collection_name",
data=data
)
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
rows.add(gson.fromJson("{\"metadata\": {\"category\": \"electronics\", \"price\": 99.99, \"brand\": \"BrandA\"}, \"pk\": 1, \"embedding\": [0.1, 0.2, 0.3]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\": {\"category\": \"home_appliances\", \"price\": 249.99, \"brand\": \"BrandB\"}, \"pk\": 2, \"embedding\": [0.4, 0.5, 0.6]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\": {\"category\": \"furniture\", \"price\": 399.99, \"brand\": \"BrandC\"}, \"pk\": 3, \"embedding\": [0.7, 0.8, 0.9]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_json_collection")
.data(rows)
.build());
const data = [
{
"metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": {"category": "home_appliances", "price": 249.99, "brand": "BrandB"},
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
"metadata": {"category": "furniture", "price": 399.99, "brand": "BrandC"},
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
}
]
client.insert({
collection_name: "my_json_collection",
data: data
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{
"metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": {"category": "home_appliances", "price": 249.99, "brand": "BrandB"},
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
"metadata": {"category": "furniture", "price": 399.99, "brand": "BrandC"},
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
}
],
"collectionName": "my_json_collection"
}'
Dalam contoh ini.
Setiap entri data mencakup bidang utama (
pk
),metadata
sebagai bidang JSON untuk menyimpan informasi seperti kategori produk, harga, dan merek.embedding
adalah bidang vektor 3 dimensi yang digunakan untuk pencarian kemiripan vektor.
Pencarian dan kueri
Bidang JSON memungkinkan pemfilteran skalar selama pencarian, meningkatkan kemampuan pencarian vektor Milvus. Anda dapat membuat kueri berdasarkan properti JSON di samping kemiripan vektor.
Menyaring kueri
Anda dapat memfilter data berdasarkan properti JSON, seperti mencocokkan nilai tertentu atau memeriksa apakah suatu angka berada dalam rentang tertentu.
filter = 'metadata["category"] == "electronics" and metadata["price"] < 150'
res = client.query(
collection_name="my_json_collection",
filter=filter,
output_fields=["metadata"]
)
print(res)
# Output
# data: ["{'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}, 'pk': 1}"]
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
String filter = "metadata[\"category\"] == \"electronics\" and metadata[\"price\"] < 150";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_json_collection")
.filter(filter)
.outputFields(Collections.singletonList("metadata"))
.build());
System.out.println(resp.getQueryResults());
// Output
//
// [QueryResp.QueryResult(entity={metadata={"category":"electronics","price":99.99,"brand":"BrandA"}, pk=1})]
client.query({
collection_name: 'my_scalar_collection',
filter: 'metadata["category"] == "electronics" and metadata["price"] < 150',
output_fields: ['metadata']
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_json_collection",
"filter": "metadata[\"category\"] == \"electronics\" and metadata[\"price\"] < 150",
"outputFields": ["metadata"]
}'
{"code":0,"cost":0,"data":[{"metadata":"{\"category\": \"electronics\", \"price\": 99.99, \"brand\": \"BrandA\"}","pk":1}]}
Pada kueri di atas, Milvus menyaring entitas dengan bidang metadata
yang memiliki kategori "electronics"
dan harga di bawah 150, dan mengembalikan entitas yang sesuai dengan kriteria ini.
Pencarian vektor dengan pemfilteran JSON
Dengan menggabungkan kemiripan vektor dengan pemfilteran JSON, Anda dapat memastikan bahwa data yang diambil tidak hanya cocok secara semantik tetapi juga memenuhi kondisi bisnis tertentu, sehingga hasil pencarian lebih tepat dan selaras dengan kebutuhan pengguna.
filter = 'metadata["brand"] == "BrandA"'
res = client.search(
collection_name="my_json_collection",
data=[[0.3, -0.6, 0.1]],
limit=5,
search_params={"params": {"nprobe": 10}},
output_fields=["metadata"],
filter=filter
)
print(res)
# Output
# data: ["[{'id': 1, 'distance': -0.2479381263256073, 'entity': {'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}}}]"]
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
String filter = "metadata[\"brand\"] == \"BrandA\"";
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_json_collection")
.annsField("embedding")
.data(Collections.singletonList(new FloatVec(new float[]{0.3f, -0.6f, 0.1f})))
.topK(5)
.outputFields(Collections.singletonList("metadata"))
.filter(filter)
.build());
System.out.println(resp.getSearchResults());
// Output
//
// [[SearchResp.SearchResult(entity={metadata={"category":"electronics","price":99.99,"brand":"BrandA"}}, score=-0.2364331, id=1)]]
client.search({
collection_name: 'my_json_collection',
data: [0.3, -0.6, 0.1],
limit: 5,
output_fields: ['metadata'],
filter: 'metadata["category"] == "electronics" and metadata["price"] < 150',
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_json_collection",
"data": [
[0.3, -0.6, 0.1]
],
"annsField": "embedding",
"limit": 5,
"searchParams":{
"params":{"nprobe":10}
},
"outputFields": ["metadata"],
"filter": "metadata[\"brand\"] == \"BrandA\""
}'
## {"code":0,"cost":0,"data":[{"distance":-0.24793813,"id":1,"metadata":"{\"category\": \"electronics\", \"price\": 99.99, \"brand\": \"BrandA\"}"}]}
Dalam contoh ini, Milvus mengembalikan 5 entitas teratas yang paling mirip dengan vektor kueri, dengan bidang metadata
yang berisi merek "BrandA"
.
Selain itu, Milvus mendukung operator pemfilteran JSON tingkat lanjut seperti JSON_CONTAINS
, JSON_CONTAINS_ALL
, dan JSON_CONTAINS_ANY
, yang dapat meningkatkan kemampuan kueri lebih lanjut. Untuk lebih jelasnya, lihat Pemfilteran Metadata.
Batasan
Batasan Pengindeksan: Karena kompleksitas struktur data, pengindeksan bidang JSON tidak didukung.
Pencocokan Tipe Data: Jika nilai kunci bidang JSON berupa bilangan bulat atau titik mengambang, nilai tersebut hanya dapat dibandingkan dengan kunci bilangan bulat atau mengambang lainnya atau bidang
INT32/64
atauFLOAT32/64
. Jika nilai kunci berupa string (VARCHAR
), maka hanya dapat dibandingkan dengan kunci string lainnya.Batasan Penamaan: Ketika menamai kunci JSON, disarankan untuk hanya menggunakan huruf, karakter numerik, dan garis bawah, karena karakter lain dapat menyebabkan masalah saat pemfilteran atau pencarian.
Menangani Nilai String: Untuk nilai string (
VARCHAR
), Milvus menyimpan string bidang JSON apa adanya tanpa konversi semantik. Sebagai contoh'a"b'
,"a'b"
,'a\\'b'
, dan"a\\"b"
disimpan seperti yang dimasukkan; namun,'a'b'
dan"a"b"
dianggap tidak valid.Menangani Kamus Bersarang: Setiap kamus bertingkat dalam nilai bidang JSON diperlakukan sebagai string.
Batas Ukuran Bidang JSON: Bidang JSON dibatasi hingga 65.536 byte.