حقل JSON
حقل JSON هو حقل قياسي يخزن معلومات إضافية إلى جانب تضمينات المتجهات، في أزواج مفاتيح-قيم. فيما يلي مثال على كيفية تخزين البيانات بتنسيق JSON:
{
"metadata": {
"product_info": {
"category": "electronics",
"brand": "BrandA"
},
"price": 99.99,
"in_stock": true,
"tags": ["summer_sale", "clearance"]
}
}
الحدود
حجم الحقل: يقتصر حجم حقول JSON على 65,536 بايت.
القواميس المتداخلة: يتم التعامل مع أي قواميس متداخلة داخل قيم حقول JSON كسلاسل عادية للتخزين.
القيم الافتراضية: لا تدعم حقول JSON القيم الافتراضية. ومع ذلك، يمكنك تعيين السمة
nullableإلىTrueللسماح بالقيم الفارغة. لمزيد من التفاصيل، راجع Nullable & Default.مطابقة النوع: إذا كانت القيمة الرئيسية لحقل JSON عبارة عن عدد صحيح أو عدد عائم فلا يمكن مقارنتها (عبر مرشحات التعبير) إلا بمفتاح رقمي آخر من نفس النوع.
التسمية: عند تسمية مفاتيح JSON، يوصى باستخدام الأحرف والأرقام والشرطات السفلية فقط. قد يسبب استخدام أحرف أخرى مشاكل عند التصفية أو البحث.
التعامل مع السلسلة: يخزن Milvus قيم السلسلة في حقول JSON كما تم إدخالها، دون تحويل دلالي. على سبيل المثال
'a"b'"a'b"و و و يتم تخزينها كما هي تمامًا.'a\\'b'"a\\"b"'a'b'و"a"b"تعتبر غير صالحة.
فهرسة JSON: عند فهرسة حقل JSON، يمكنك تحديد مسار واحد أو أكثر في حقل JSON لتسريع التصفية. يزيد كل مسار إضافي من عبء الفهرسة الزائد، لذا خطط لاستراتيجية الفهرسة بعناية. لمزيد من الاعتبارات حول فهرسة حقل JSON، راجع اعتبارات فهرسة JSON.
إضافة حقل JSON
لإضافة حقل JSON metadata إلى مخطط مجموعتك، استخدم DataType.JSON. يحدد المثال أدناه حقل JSON metadata الذي يسمح بقيم فارغة:
# Import necessary libraries
from pymilvus import MilvusClient, DataType
# Define server address
SERVER_ADDR = "http://localhost:19530"
# Create a MilvusClient instance
client = MilvusClient(uri=SERVER_ADDR)
# Define the collection schema
schema = client.create_schema(
auto_id=False,
enable_dynamic_fields=True,
)
# Add a JSON field that supports null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)
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)
.isNullable(true)
.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 (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/index"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
schema := entity.NewSchema()
schema.WithField(entity.NewField().
WithName("pk").
WithDataType(entity.FieldTypeInt64).
WithIsAutoID(true),
).WithField(entity.NewField().
WithName("embedding").
WithDataType(entity.FieldTypeFloatVector).
WithDim(3),
).WithField(entity.NewField().
WithName("metadata").
WithDataType(entity.FieldTypeJSON),
)
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,
\"enableDynamicField\": true,
\"fields\": [
$jsonField,
$pkField,
$vectorField
]
}"
قم بتعيين
enable_dynamic_fields=Trueإذا كنت بحاجة إلى إدراج حقول إضافية غير محددة في المستقبل.استخدم
nullable=Trueللسماح بوجود كائنات JSON مفقودة أو فارغة.
تعيين بارامترات الفهرس
تساعد الفهرسة ميلفوس على تصفية أو البحث بسرعة عبر كميات كبيرة من البيانات. في ملفوس، الفهرسة هي
إلزامي للحقول المتجهة (لتشغيل عمليات البحث عن التشابه بكفاءة).
اختياري لحقول JSON (لتسريع عمليات التصفية العددية على مسارات JSON محددة).
فهرسة حقل JSONCompatible with Milvus 2.5.10+
بشكل افتراضي، لا تتم فهرسة حقول JSON، لذا يجب على أي استعلامات تصفية (على سبيل المثال، metadata["price"] < 100) مسح جميع الصفوف. إذا كنت ترغب في تسريع الاستعلامات على مسارات محددة داخل الحقل metadata ، يمكنك إنشاء فهرس مقلوب على كل مسار تهتم به.
في هذا المثال، سننشئ فهرسين على مسارات مختلفة داخل حقل JSON metadata:
index_params = client.prepare_index_params()
# Example 1: Index the 'category' key inside 'product_info' as a string
index_params.add_index(
field_name="metadata", # JSON field name to index
index_type="INVERTED", # Index type. Set to INVERTED
index_name="json_index_1", # Index name
params={
"json_path": "metadata[\"product_info\"][\"category\"]", # Path in JSON field to index
"json_cast_type": "varchar" # Data type that the extracted JSON values will be cast to
}
)
# Example 2: Index 'price' as a numeric type (double)
index_params.add_index(
field_name="metadata",
index_type="INVERTED",
index_name="json_index_2",
params={
"json_path": "metadata[\"price\"]",
"json_cast_type": "double"
}
)
import io.milvus.v2.common.IndexParam;
List<IndexParam> indexes = new ArrayList<>();
Map<String,Object> extraParams_1 = new HashMap<>();
extraParams_1.put("json_path", "metadata[\"product_info\"][\"category\"]");
extraParams_1.put("json_cast_type", "varchar");
indexes.add(IndexParam.builder()
.fieldName("metadata")
.indexName("json_index_1")
.indexType(IndexParam.IndexType.INVERTED)
.extraParams(extraParams_1)
.build());
Map<String,Object> extraParams_2 = new HashMap<>();
extraParams_2.put("json_path", "metadata[\"price\"]");
extraParams_2.put("json_cast_type", "double");
indexes.add(IndexParam.builder()
.fieldName("metadata")
.indexName("json_index_2")
.indexType(IndexParam.IndexType.INVERTED)
.extraParams(extraParams_2)
.build());
jsonIndex1 := index.NewJSONPathIndex(index.Inverted, "varchar", `metadata["product_info"]["category"]`)
jsonIndex2 := index.NewJSONPathIndex(index.Inverted, "double", `metadata["price"]`)
indexOpt1 := milvusclient.NewCreateIndexOption("my_collection", "metadata", jsonIndex1)
indexOpt2 := milvusclient.NewCreateIndexOption("my_collection", "metadata", jsonIndex2)
const indexParams = [
{
field_name: "metadata",
index_type: "INVERTED",
index_name: "json_index_1",
params: {
json_path: "metadata[\"product_info\"][\"category\"]",
json_cast_type: "varchar"
}
},
{
field_name: "metadata",
index_type: "INVERTED",
index_name: "json_index_2",
params: {
json_path: "metadata[\"price\"]",
json_cast_type: "double"
}
}
]
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"indexParams": [
{
"fieldName": "metadata",
"indexName": "json_index_1",
"indexType": "INVERTED",
"params": {
"json_path": "metadata[\"product_info\"][\"category\"]",
"json_cast_type": "varchar"
}
}
]
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"indexParams": [
{
"fieldName": "metadata",
"indexName": "json_index_2",
"indexType": "INVERTED",
"params": {
"json_path": "metadata[\"price\"]",
"json_cast_type": "double"
}
}
]
}'
المعلمة |
الوصف |
مثال القيمة |
|---|---|---|
|
اسم حقل JSON في مخططك. |
|
|
نوع الفهرس المراد إنشاؤه؛ حاليًا فقط |
|
|
(اختياري) اسم فهرس مخصص. حدد أسماء مختلفة إذا قمت بإنشاء فهارس متعددة على نفس حقل JSON. |
|
|
تحديد مسار JSON المراد فهرسته. يمكنك استهداف المفاتيح المتداخلة أو مواضع المصفوفات أو كليهما (على سبيل المثال، |
|
|
نوع البيانات الذي سيقوم ميلفوس بإرسال قيم JSON المستخرجة إليه عند بناء الفهرس. القيم الصالحة:
|
|
اعتبارات حول فهرسة JSON
منطق الفهرسة:
إذا أنشأت فهرسًا من النوع المزدوج (
json_cast_type="double")، يمكن فقط لشروط التصفية من النوع الرقمي استخدام الفهرس. إذا قارن عامل التصفية فهرسًا مزدوجًا بشرط غير رقمي، فإن ميلفوس يعود إلى البحث بالقوة الغاشمة.إذا قمت بإنشاء فهرس من نوع varchar (
json_cast_type="varchar")، يمكن فقط لشروط التصفية من نوع السلسلة استخدام الفهرس. خلاف ذلك، يعود ميلفوس إلى القوة الغاشمة.تتصرف الفهرسةالمنطقية بشكل مشابه للنوع المتغير.
تعبيرات المصطلحات:
- يمكنك استخدام
json["field"] in [value1, value2, …]. ومع ذلك، يعمل الفهرس فقط للقيم العددية المخزنة تحت هذا المسار. إذا كانjson["field"]عبارة عن مصفوفة، يعود الاستعلام إلى القوة الغاشمة (الفهرسة من نوع الصفيف غير مدعومة بعد).
- يمكنك استخدام
الدقة العددية:
- داخليًا، يقوم ميلفوس بفهرسة جميع الحقول الرقمية كمضاعفات. إذا تجاوزت قيمة رقمية 2 فإنها تفقد الدقة، وقد لا تتطابق الاستعلامات على تلك القيم خارج النطاق تمامًا.
تكامل البيانات:
- لا يقوم Milvus بتحليل مفاتيح JSON أو تحويلها خارج نطاق الصب المحدد. إذا كانت البيانات المصدر غير متناسقة (على سبيل المثال، تخزن بعض الصفوف سلسلة للمفتاح
"k"بينما تخزن أخرى رقمًا)، فلن تتم فهرسة بعض الصفوف.
- لا يقوم Milvus بتحليل مفاتيح JSON أو تحويلها خارج نطاق الصب المحدد. إذا كانت البيانات المصدر غير متناسقة (على سبيل المثال، تخزن بعض الصفوف سلسلة للمفتاح
فهرسة حقل متجه
يقوم المثال التالي بإنشاء فهرس على الحقل المتجه embedding ، باستخدام نوع الفهرس AUTOINDEX. باستخدام هذا النوع، يختار ميلفوس تلقائيًا الفهرس الأنسب بناءً على نوع البيانات. يمكنك أيضًا تخصيص نوع الفهرس والبارامترات لكل حقل. لمزيد من التفاصيل، راجع شرح الفهرس.
# Set index params
# Index `embedding` with AUTOINDEX and specify similarity metric type
index_params.add_index(
field_name="embedding",
index_name="vector_index",
index_type="AUTOINDEX", # Use automatic indexing to simplify complex index settings
metric_type="COSINE" # Specify similarity metric type, options include L2, COSINE, or IP
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
indexes.add(IndexParam.builder()
.fieldName("embedding")
.indexName("vector_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE)
.build());
vectorIndex := index.NewAutoIndex(entity.COSINE)
indexOpt := milvusclient.NewCreateIndexOption("my_collection", "embedding", vectorIndex)
indexParams.push({
index_name: 'embedding_index',
field_name: 'embedding',
index_name: 'vector_index',
metricType: MetricType.CONSINE,
index_type: IndexType.AUTOINDEX,
));
export indexParams='[
{
"fieldName": "embedding",
"indexName": "vector_index",
"metricType": "COSINE",
"indexType": "AUTOINDEX"
}
]'
إنشاء مجموعة
بمجرد تعريف المخطط والفهرس، قم بإنشاء مجموعة تتضمن حقل JSON.
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params
)
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOpt1, indexOpt2, indexOpt))
if err != nil {
fmt.Println(err.Error())
// handler err
}
await client.create_collection({
collection_name: "my_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_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
إدراج البيانات
بعد إنشاء المجموعة، أدرج الكيانات التي تطابق المخطط.
# Sample data
data = [
{
"metadata": {
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": True,
"tags": ["summer_sale"]
},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": None, # Entire JSON object is null
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
# JSON field is completely missing
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
},
{
# Some sub-keys are null
"metadata": {
"product_info": {"category": None, "brand": "BrandB"},
"price": 59.99,
"in_stock": None
},
"pk": 4,
"embedding": [0.56, 0.38, 0.21]
}
]
client.insert(
collection_name="my_collection",
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\":{\"product_info\":{\"category\":\"electronics\",\"brand\":\"BrandA\"},\"price\":99.99,\"in_stock\":True,\"tags\":[\"summer_sale\"]},\"pk\":1,\"embedding\":[0.12,0.34,0.56]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\":null,\"pk\":2,\"embedding\":[0.56,0.78,0.90]}", JsonObject.class));
rows.add(gson.fromJson("{\"pk\":3,\"embedding\":[0.91,0.18,0.23]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\":{\"product_info\":{\"category\":null,\"brand\":\"BrandB\"},\"price\":59.99,\"in_stock\":null},\"pk\":4,\"embedding\":[0.56,0.38,0.21]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(rows)
.build());
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("pk", []int64{1, 2, 3, 4}).
WithFloatVectorColumn("embedding", 3, [][]float32{
{0.12, 0.34, 0.56},
{0.56, 0.78, 0.90},
{0.91, 0.18, 0.23},
{0.56, 0.38, 0.21},
}).WithColumns(
column.NewColumnJSONBytes("metadata", [][]byte{
[]byte(`{
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": True,
"tags": ["summer_sale"]
}`),
[]byte(`null`),
[]byte(`null`),
[]byte(`"metadata": {
"product_info": {"category": None, "brand": "BrandB"},
"price": 59.99,
"in_stock": None
}`),
}),
))
if err != nil {
fmt.Println(err.Error())
// handle err
}
const data = [
{
"metadata": {
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": True,
"tags": ["summer_sale"]
},
"pk": 1,
"embedding": [0.12, 0.34, 0.56]
},
{
"metadata": None, # Entire JSON object is null
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
# JSON field is completely missing
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
},
{
# Some sub-keys are null
"metadata": {
"product_info": {"category": None, "brand": "BrandB"},
"price": 59.99,
"in_stock": None
},
"pk": 4,
"embedding": [0.56, 0.38, 0.21]
}
];
await client.insert({
collection_name: "my_collection",
data: data
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"data": [
{
"metadata": {
"product_info": {"category": "electronics", "brand": "BrandA"},
"price": 99.99,
"in_stock": true,
"tags": ["summer_sale"]
},
"varchar_field2": "High quality product",
"pk": 1,
"embedding": [0.1, 0.2, 0.3]
},
{
"metadata": null,
"pk": 2,
"embedding": [0.56, 0.78, 0.90]
},
{
"pk": 3,
"embedding": [0.91, 0.18, 0.23]
},
{
"metadata": {
"product_info": {"category": null, "brand": "BrandB"},
"price": 59.99,
"in_stock": null
},
"pk": 4,
"embedding": [0.56, 0.38, 0.21]
}
],
"collectionName": "my_collection"
}'
الاستعلام باستخدام تعبيرات التصفية
بعد إدراج الكيانات، استخدم الأسلوب query لاسترداد الكيانات التي تطابق تعبيرات التصفية المحددة.
بالنسبة لحقول JSON التي تسمح بقيم فارغة، سيتم التعامل مع الحقل على أنه فارغ إذا كان كائن JSON بأكمله مفقودًا أو تم تعيينه إلى None. لمزيد من المعلومات، راجع حقول JSON ذات القيم الفارغة.
لاسترداد الكيانات حيث metadata ليست فارغة:
# Query to filter out records with null metadata
filter = 'metadata is not null'
res = client.query(
collection_name="my_collection",
filter=filter,
output_fields=["metadata", "pk"]
)
# Expected result:
# Rows with pk=1 and pk=4 have valid, non-null metadata.
# Rows with pk=2 (metadata=None) and pk=3 (no metadata key) are excluded.
print(res)
# Output:
# data: [
# "{'metadata': {'product_info': {'category': 'electronics', 'brand': 'BrandA'}, 'price': 99.99, 'in_stock': True, 'tags': ['summer_sale']}, 'pk': 1}",
# "{'metadata': {'product_info': {'category': None, 'brand': 'BrandB'}, 'price': 59.99, 'in_stock': None}, 'pk': 4}"
# ]
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
String filter = "metadata is not null";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter(filter)
.outputFields(Arrays.asList("metadata", "pk"))
.build());
System.out.println(resp.getQueryResults());
// Output
//
// [
// QueryResp.QueryResult(entity={metadata={"product_info":{"category":"electronics","brand":"BrandA"},"price":99.99,"in_stock":true,"tags":["summer_sale"]}, pk=1}),
// QueryResp.QueryResult(entity={metadata={"product_info":{"category":null,"brand":"BrandB"},"price":59.99,"in_stock":null}, pk=4})
// ]
filter := "metadata is not null"
rs, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter(filter).
WithOutputFields("metadata", "pk"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println("pk", rs.GetColumn("pk").FieldData().GetScalars())
fmt.Println("metadata", rs.GetColumn("metadata").FieldData().GetScalars())
await 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_collection",
"filter": "metadata is not null",
"outputFields": ["metadata", "pk"]
}'
#{"code":0,"cost":0,"data":[{"metadata":"{\"product_info\": {\"category\": \"electronics\", \"brand\": \"BrandA\"}, \"price\": 99.99, \"in_stock\": true, \"tags\": [\"summer_sale\"]}","pk":1},{"metadata":"","pk":2},{"metadata":"","pk":3},{"metadata":"{\"product_info\": {\"category\": null, \"brand\": \"BrandB\"}, \"price\": 59.99, \"in_stock\": null}","pk":4}]}
لاسترداد الكيانات حيث metadata["product_info"]["category"] هو "electronics":
filter = 'metadata["product_info"]["category"] == "electronics"'
res = client.query(
collection_name="my_collection",
filter=filter,
output_fields=["metadata", "pk"]
)
# Expected result:
# - Only pk=1 has "category": "electronics".
# - pk=4 has "category": None, so it doesn't match.
# - pk=2 and pk=3 have no valid metadata.
print(res)
# Output:
# data: [
# "{'pk': 1, 'metadata': {'product_info': {'category': 'electronics', 'brand': 'BrandA'}, 'price': 99.99, 'in_stock': True, 'tags': ['summer_sale']}}"
# ]
String filter = "metadata[\"product_info\"][\"category\"] == \"electronics\"";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter(filter)
.outputFields(Arrays.asList("metadata", "pk"))
.build());
System.out.println(resp.getQueryResults());
// Output
// [QueryResp.QueryResult(entity={metadata={"product_info":{"category":"electronics","brand":"BrandA"},"price":99.99,"in_stock":true,"tags":["summer_sale"]}, pk=1})]
filter = `metadata["product_info"]["category"] == "electronics"`
rs, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter(filter).
WithOutputFields("metadata", "pk"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println("pk", rs.GetColumn("pk").FieldData().GetScalars())
fmt.Println("metadata", rs.GetColumn("metadata").FieldData().GetScalars())
const filter = 'metadata["category"] == "electronics"';
const res = await client.query({
collection_name: "my_collection",
filter: filter,
output_fields: ["metadata", "pk"]
});
// Example output:
// {
//. data: [
// {'pk': 1, 'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}}
// ]
// }
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"filter": "metadata[\"product_info\"][\"category\"] == \"electronics\"",
"outputFields": ["metadata", "pk"]
}'
#{"code":0,"cost":0,"data":[{"metadata":"{\"product_info\": {\"category\": \"electronics\", \"brand\": \"BrandA\"}, \"price\": 99.99, \"in_stock\": true, \"tags\": [\"summer_sale\"]}","pk":1}]}
البحث المتجه مع تعبيرات التصفية
بالإضافة إلى تصفية الحقل القياسي الأساسي، يمكنك دمج عمليات البحث عن تشابه المتجهات مع مرشحات الحقل القياسي. على سبيل المثال، يوضح الرمز التالي كيفية إضافة عامل تصفية الحقل القياسي إلى بحث متجه:
filter = 'metadata["product_info"]["brand"] == "BrandA"'
res = client.search(
collection_name="my_collection",
data=[[0.3, -0.6, 0.1]],
limit=5,
search_params={"params": {"nprobe": 10}},
output_fields=["metadata"],
filter=filter
)
# Expected result:
# - Only pk=1 has "brand": "BrandA" in metadata["product_info"].
# - pk=4 has "brand": "BrandB".
# - pk=2 and pk=3 have no valid metadata.
# Hence, only pk=1 matches the filter.
print(res)
# Output:
# data: [
# "[{'id': 1, 'distance': -0.2479381263256073, 'entity': {'metadata': {'product_info': {'category': 'electronics', 'brand': 'BrandA'}, 'price': 99.99, 'in_stock': True, 'tags': ['summer_sale']}}}]"
# ]
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;
String filter = "metadata[\"product_info\"][\"brand\"] == \"BrandA\"";
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_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={"product_info":{"category":"electronics","brand":"BrandA"},"price":99.99,"in_stock":true,"tags":["summer_sale"]}}, score=-0.24793813, id=1)
// ]
// ]
queryVector := []float32{0.3, -0.6, -0.1}
filter = "metadata[\"product_info\"][\"brand\"] == \"BrandA\""
annParam := index.NewCustomAnnParam()
annParam.WithExtraParam("nprobe", 10)
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"my_collection", // collectionName
5, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("embedding").
WithFilter(filter).
WithOutputFields("metadata").
WithAnnParam(annParam))
if err != nil {
fmt.Println(err.Error())
// handle error
}
for _, resultSet := range resultSets {
fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
fmt.Println("Scores: ", resultSet.Scores)
fmt.Println("metadata", resultSet.GetColumn("metadata").FieldData().GetScalars())
}
await client.search({
collection_name: 'my_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/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"data": [
[0.3, -0.6, 0.1]
],
"annsField": "embedding",
"limit": 5,
"searchParams": {
"params": {
"nprobe": 10
}
},
"outputFields": ["metadata"],
"filter": "metadata[\"product_info\"][\"brand\"] == \"BrandA\""
}'
##{"code":0,"cost":0,"data":[{"metadata":"{\"product_info\": {\"category\": \"electronics\", \"brand\": \"BrandA\"}, \"price\": 99.99, \"in_stock\": true, \"tags\": [\"summer_sale\"]}","pk":1}]}
بالإضافة إلى ذلك، يدعم Milvus عوامل تصفية JSON المتقدمة مثل JSON_CONTAINS و JSON_CONTAINS_ALL و JSON_CONTAINS_ANY ، والتي يمكن أن تعزز قدرات الاستعلام بشكل أكبر. لمزيد من التفاصيل، راجع مشغلات JSON.