الحقل الديناميكي
يسمح لك ميلفوس بإدراج كيانات ذات هياكل مرنة ومتطورة من خلال ميزة خاصة تسمى الحقل الديناميكي. يتم تنفيذ هذا الحقل كحقل JSON مخفي يسمى $meta ، والذي يخزن تلقائيًا أي حقول في بياناتك غير محددة بشكل صريح في مخطط المجموعة.
كيف يعمل الحقل الديناميكي
عند تمكين الحقل الديناميكي، يضيف ميلفوس حقلاً مخفياً $meta إلى كل كيان. هذا الحقل هو من نوع JSON، مما يعني أنه يمكن تخزين أي بنية بيانات متوافقة مع JSON ويمكن فهرستها باستخدام بناء جملة مسار JSON.
أثناء إدراج البيانات، يتم تخزين أي حقل غير معلن في المخطط تلقائيًا كزوج من مفتاح وقيمة داخل هذا الحقل الديناميكي.
لست بحاجة إلى إدارة $meta يدويًا - فـ "ميلفوس" يتعامل معها بشفافية.
على سبيل المثال، إذا كان مخطط مجموعتك يحدد فقط id و vector ، وقمت بإدراج الكيان التالي:
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"name": "Item A", // Not in schema
"category": "books" // Not in schema
}
مع تمكين ميزة الحقل الديناميكي، يقوم ميلفوس بتخزينه داخليًا على أنه:
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"$meta": {
"name": "Item A",
"category": "books"
}
}
يسمح لك هذا بتطوير بنية البيانات الخاصة بك دون تغيير المخطط.
تتضمن حالات الاستخدام الشائعة ما يلي:
تخزين الحقول الاختيارية أو التي يتم استرجاعها بشكل غير متكرر
التقاط البيانات الوصفية التي تختلف حسب الكيان
دعم التصفية المرنة عبر الفهارس على مفاتيح حقول ديناميكية محددة
أنواع البيانات المدعومة
يدعم الحقل الديناميكي جميع أنواع البيانات القياسية التي يوفرها ميلفوس، بما في ذلك القيم البسيطة والمعقدة. تنطبق أنواع البيانات هذه على ** قيم المفاتيح المخزنة في $meta.
تشمل الأنواع المدعومة ما يلي:
سلسلة (
VARCHAR)عدد صحيح (
INT8،INT32، ،INT64)النقطة العائمة (
FLOAT،DOUBLE)منطقية (
BOOL)صفيف القيم القياسية (
ARRAY)كائنات JSON (
JSON)
مثال:
{
"brand": "Acme",
"price": 29.99,
"in_stock": true,
"tags": ["new", "hot"],
"specs": {
"weight": "1.2kg",
"dimensions": { "width": 10, "height": 20 }
}
}
سيتم تخزين كل من المفاتيح والقيم المذكورة أعلاه داخل الحقل $meta.
تمكين الحقل الديناميكي
لاستخدام ميزة الحقل الديناميكي، قم بتعيين enable_dynamic_field=True عند إنشاء مخطط المجموعة:
from pymilvus import MilvusClient, DataType
# Initialize client
client = MilvusClient(uri="http://localhost:19530")
# Create schema with dynamic field enabled
schema = client.create_schema(
auto_id=False,
enable_dynamic_field=True,
)
# Add explicitly defined fields
schema.add_field(field_name="my_id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="my_vector", datatype=DataType.FLOAT_VECTOR, dim=5)
# Create the collection
client.create_collection(
collection_name="my_collection",
schema=schema
)
import io.milvus.v2.client.*;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.AddFieldReq;
ConnectConfig config = ConnectConfig.builder()
.uri("http://localhost:19530")
.build();
MilvusClientV2 client = new MilvusClientV2(config);
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
.enableDynamicField(true)
.build();
schema.addField(AddFieldReq.builder()
.fieldName("my_id")
.dataType(DataType.Int64)
.isPrimaryKey(Boolean.TRUE)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("my_vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.build();
client.createCollection(requestCreate);
import { MilvusClient, DataType, CreateCollectionReq } from '@zilliz/milvus2-sdk-node';
// Initialize client
const client = new MilvusClient({ address: 'localhost:19530' });
// Create collection
const res = await client.createCollection({
collection_name: 'my_collection',
schema: [
{
name: 'my_id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: false,
},
{
name: 'my_vector',
data_type: DataType.FloatVector,
type_params: {
dim: '5',
}
],
enable_dynamic_field: true
});
import (
"context"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "localhost:19530",
})
if err != nil {
return err
}
schema := entity.NewSchema().WithDynamicFieldEnabled(true)
schema.WithField(entity.NewField().
WithName("my_id").pk
WithDataType(entity.FieldTypeInt64).
WithIsPrimaryKey(true),
).WithField(entity.NewField().
WithName("my_vector").
WithDataType(entity.FieldTypeFloatVector).
WithDim(5),
)
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema))
if err != nil {
return err
}
# restful
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export myIdField='{
"fieldName": "my_id",
"dataType": "Int64",
"isPrimary": true,
"autoID": false
}'
export myVectorField='{
"fieldName": "my_vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 5
}
}'
export schema="{
\"autoID\": false,
\"enableDynamicField\": true,
\"fields\": [
$myIdField,
$myVectorField
]
}"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"schema\": $schema
}"
إدراج كيانات في المجموعة
يسمح لك الحقل الديناميكي بإدراج حقول إضافية غير محددة في المخطط. سيتم تخزين هذه الحقول تلقائيًا في $meta.
entities = [
{
"my_id": 1, # Explicitly defined primary field
"my_vector": [0.1, 0.2, 0.3, 0.4, 0.5], # Explicitly defined vector field
"overview": "Great product", # Scalar key not defined in schema
"words": 150, # Scalar key not defined in schema
"dynamic_json": { # JSON key not defined in schema
"varchar": "some text",
"nested": {
"value": 42.5
},
"string_price": "99.99" # Number stored as string
}
}
]
client.insert(collection_name="my_collection", data=entities)
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
Gson gson = new Gson();
JsonObject row = new JsonObject();
row.addProperty("my_id", 1);
row.add("my_vector", gson.toJsonTree(Arrays.asList(0.1, 0.2, 0.3, 0.4, 0.5)));
row.addProperty("overview", "Great product");
row.addProperty("words", 150);
JsonObject dynamic = new JsonObject();
dynamic.addProperty("varchar", "some text");
dynamic.addProperty("string_price", "99.99");
JsonObject nested = new JsonObject();
nested.addProperty("value", 42.5);
dynamic.add("nested", nested);
row.add("dynamic_json", dynamic);
client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(row))
.build());
const entities = [
{
my_id: 1,
my_vector: [0.1, 0.2, 0.3, 0.4, 0.5],
overview: 'Great product',
words: 150,
dynamic_json: {
varchar: 'some text',
nested: {
value: 42.5,
},
string_price: '99.99',
},
},
];
const res = await client.insert({
collection_name: 'my_collection',
data: entities,
});
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("my_id", []int64{1}).
WithFloatVectorColumn("my_vector", 5, [][]float32{
{0.1, 0.2, 0.3, 0.4, 0.5},
}).WithColumns(
column.NewColumnVarChar("overview", []string{"Great product"}),
column.NewColumnInt32("words", []int32{150}),
column.NewColumnJSONBytes("dynamic_json", [][]byte{
[]byte(`{
varchar: 'some text',
nested: {
value: 42.5,
},
string_price: '99.99',
}`),
}),
))
if err != nil {
return err
}
# restful
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data '{
"data": [
{
"my_id": 1,
"my_vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"overview": "Great product",
"words": 150,
"dynamic_json": {
"varchar": "some text",
"nested": {
"value": 42.5
},
"string_price": "99.99"
}
}
],
"collectionName": "my_collection"
}'
مفاتيح الفهرسة في الحقل الديناميكيCompatible with Milvus 2.5.11+
يسمح لك Milvus باستخدام فهرسة مسار JSON لإنشاء فهارس على مفاتيح محددة داخل الحقل الديناميكي. يمكن أن تكون هذه قيمًا قياسية أو قيمًا متداخلة في كائنات JSON.
فهرسة مفاتيح الحقول الديناميكية اختيارية. لا يزال بإمكانك الاستعلام أو التصفية حسب مفاتيح الحقول الديناميكية بدون فهرس، ولكن قد يؤدي ذلك إلى أداء أبطأ بسبب البحث بالقوة الغاشمة.
بناء جملة فهرسة مسار JSON
لإنشاء فهرس مسار JSON، حدد:
مسار JSON (
json_path): المسار إلى المفتاح أو الحقل المتداخل داخل كائن JSON الذي تريد فهرسته.مثال:
metadata["category"]هذا يحدد المكان الذي يجب أن يبحث فيه محرك الفهرسة داخل بنية JSON.
نوع إرسال JSON (
json_cast_type): نوع البيانات الذي يجب أن يستخدمه Milvus عند تفسير وفهرسة القيمة في المسار المحدد.يجب أن يتطابق هذا النوع مع نوع البيانات الفعلي للحقل الذي تتم فهرسته.
للاطلاع على قائمة كاملة، ارجع إلى أنواع مسبوكات JSON المدعومة.
استخدام مسار JSON لفهرسة مفاتيح الحقل الديناميكي
بما أن الحقل الديناميكي هو حقل JSON، يمكنك فهرسة أي مفتاح داخله باستخدام صيغة مسار JSON. يعمل هذا مع كل من القيم العددية البسيطة والبنى المتداخلة المعقدة.
أمثلة على مسار JSON:
للمفاتيح البسيطة:
overview,wordsللمفاتيح المتداخلة:
dynamic_json['varchar'],dynamic_json['nested']['value']
index_params = client.prepare_index_params()
# Index a simple string key
index_params.add_index(
field_name="overview", # Key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="overview_index", # Unique index name
params={
"json_cast_type": "varchar", # Data type that Milvus uses when indexing the values
"json_path": "overview" # JSON path to the key
}
)
# Index a simple numeric key
index_params.add_index(
field_name="words", # Key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="words_index", # Unique index name
params={
"json_cast_type": "double", # Data type that Milvus uses when indexing the values
"json_path": "words" # JSON path to the key
}
)
# Index a nested key within a JSON object
index_params.add_index(
field_name="dynamic_json", # JSON key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="json_varchar_index", # Unique index name
params={
"json_cast_type": "varchar", # Data type that Milvus uses when indexing the values
"json_path": "dynamic_json['varchar']" # JSON path to the nested key
}
)
# Index a deeply nested key
index_params.add_index(
field_name="dynamic_json",
index_type="AUTOINDEX", # Must be set to AUTOINDEX or INVERTED for JSON path indexing
index_name="json_nested_index", # Unique index name
params={
"json_cast_type": "double",
"json_path": "dynamic_json['nested']['value']"
}
)
import io.milvus.v2.common.IndexParam;
Map<String,Object> extraParams1 = new HashMap<>();
extraParams1.put("json_path", "overview");
extraParams1.put("json_cast_type", "varchar");
indexParams.add(IndexParam.builder()
.fieldName("overview")
.indexName("overview_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams1)
.build());
Map<String,Object> extraParams2 = new HashMap<>();
extraParams2.put("json_path", "words");
extraParams2.put("json_cast_type", "double");
indexParams.add(IndexParam.builder()
.fieldName("words")
.indexName("words_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams2)
.build());
Map<String,Object> extraParams3 = new HashMap<>();
extraParams3.put("json_path", "dynamic_json['varchar']");
extraParams3.put("json_cast_type", "varchar");
indexParams.add(IndexParam.builder()
.fieldName("dynamic_json")
.indexName("json_varchar_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams3)
.build());
Map<String,Object> extraParams4 = new HashMap<>();
extraParams4.put("json_path", "dynamic_json['nested']['value']");
extraParams4.put("json_cast_type", "double");
indexParams.add(IndexParam.builder()
.fieldName("dynamic_json")
.indexName("json_nested_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams4)
.build());
const indexParams = [
{
collection_name: 'my_collection',
field_name: 'overview',
index_name: 'overview_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_path: 'overview',
json_cast_type: 'varchar',
},
},
{
collection_name: 'my_collection',
field_name: 'words',
index_name: 'words_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_path: 'words',
json_cast_type: 'double',
},
},
{
collection_name: 'my_collection',
field_name: 'dynamic_json',
index_name: 'json_varchar_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_cast_type: 'varchar',
json_path: "dynamic_json['varchar']",
},
},
{
collection_name: 'my_collection',
field_name: 'dynamic_json',
index_name: 'json_nested_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_cast_type: 'double',
json_path: "dynamic_json['nested']['value']",
},
},
];
import (
"github.com/milvus-io/milvus/client/v2/index"
)
jsonIndex1 := index.NewJSONPathIndex(index.AUTOINDEX, "varchar", "overview")
.WithIndexName("overview_index")
jsonIndex2 := index.NewJSONPathIndex(index.AUTOINDEX, "double", "words")
.WithIndexName("words_index")
jsonIndex3 := index.NewJSONPathIndex(index.AUTOINDEX, "varchar", `dynamic_json['varchar']`)
.WithIndexName("json_varchar_index")
jsonIndex4 := index.NewJSONPathIndex(index.AUTOINDEX, "double", `dynamic_json['nested']['value']`)
.WithIndexName("json_nested_index")
indexOpt1 := milvusclient.NewCreateIndexOption("my_collection", "overview", jsonIndex1)
indexOpt2 := milvusclient.NewCreateIndexOption("my_collection", "words", jsonIndex2)
indexOpt3 := milvusclient.NewCreateIndexOption("my_collection", "dynamic_json", jsonIndex3)
indexOpt4 := milvusclient.NewCreateIndexOption("my_collection", "dynamic_json", jsonIndex4)
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export overviewIndex='{
"fieldName": "dynamic_json",
"indexName": "overview_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "varchar",
"json_path": "dynamic_json[\"overview\"]"
}
}'
export wordsIndex='{
"fieldName": "dynamic_json",
"indexName": "words_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "double",
"json_path": "dynamic_json[\"words\"]"
}
}'
export varcharIndex='{
"fieldName": "dynamic_json",
"indexName": "json_varchar_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "varchar",
"json_path": "dynamic_json[\"varchar\"]"
}
}'
export nestedIndex='{
"fieldName": "dynamic_json",
"indexName": "json_nested_index",
"params": {
"index_type": "AUTOINDEX",
"json_cast_type": "double",
"json_path": "dynamic_json[\"nested\"][\"value\"]"
}
}'
استخدم دوال JSON cast لتحويل النوعCompatible with Milvus 2.5.14+
إذا كان مفتاح الحقل الديناميكي يحتوي على قيم بتنسيق غير صحيح، (على سبيل المثال الأرقام المخزنة كسلاسل)، يمكنك استخدام دالة الإرسال لتحويلها:
# Convert a string to double before indexing
index_params.add_index(
field_name="dynamic_json", # JSON key name
index_type="AUTOINDEX",
index_name="json_string_price_index",
params={
"json_path": "dynamic_json['string_price']",
"json_cast_type": "double", # Must be the output type of the cast function
"json_cast_function": "STRING_TO_DOUBLE" # Case insensitive; convert string to double
}
)
Map<String,Object> extraParams5 = new HashMap<>();
extraParams5.put("json_path", "dynamic_json['string_price']");
extraParams5.put("json_cast_type", "double");
indexParams.add(IndexParam.builder()
.fieldName("dynamic_json")
.indexName("json_string_price_index")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams5)
.build());
indexParams.push({
collection_name: 'my_collection',
field_name: 'dynamic_json',
index_name: 'json_string_price_index',
index_type: 'AUTOINDEX',
metric_type: 'NONE',
params: {
json_path: "dynamic_json['string_price']",
json_cast_type: 'double',
json_cast_function: 'STRING_TO_DOUBLE',
},
});
jsonIndex5 := index.NewJSONPathIndex(index.AUTOINDEX, "double", `dynamic_json['string_price']`)
.WithIndexName("json_string_price_index")
indexOpt5 := milvusclient.NewCreateIndexOption("my_collection", "dynamic_json", jsonIndex5)
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export stringPriceIndex='{
"fieldName": "dynamic_json",
"indexName": "json_string_price_index",
"params": {
"index_type": "AUTOINDEX",
"json_path": "dynamic_json[\"string_price\"]",
"json_cast_type": "double",
"json_cast_function": "STRING_TO_DOUBLE"
}
}'
إذا فشل تحويل النوع (على سبيل المثال القيمة
"not_a_number"لا يمكن تحويلها إلى رقم)، يتم تخطي القيمة وإلغاء فهرستها.للحصول على تفاصيل حول معلمات دالة الإرسال، راجع حقل JSON.
تطبيق الفهارس على المجموعة
بعد تحديد معلمات الفهرس، يمكنك تطبيقها على المجموعة باستخدام create_index():
client.create_index(
collection_name="my_collection",
index_params=index_params
)
import io.milvus.v2.service.index.request.CreateIndexReq;
client.createIndex(CreateIndexReq.builder()
.collectionName("my_collection")
.indexParams(indexParams)
.build());
await client.createIndex(indexParams);
indexTask1, err := client.CreateIndex(ctx, indexOpt1)
if err != nil {
return err
}
indexTask2, err := client.CreateIndex(ctx, indexOpt2)
if err != nil {
return err
}
indexTask3, err := client.CreateIndex(ctx, indexOpt3)
if err != nil {
return err
}
indexTask4, err := client.CreateIndex(ctx, indexOpt4)
if err != nil {
return err
}
indexTask5, err := client.CreateIndex(ctx, indexOpt5)
if err != nil {
return err
}
# restful
export indexParams="[
$varcharIndex,
$nestedIndex,
$overviewIndex,
$wordsIndex,
$stringPriceIndex
]"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"indexParams\": $indexParams
}"
تصفية حسب مفاتيح الحقول الديناميكية
بعد إدراج الكيانات ذات مفاتيح الحقول الديناميكية، يمكنك تصفيتها باستخدام تعبيرات التصفية القياسية.
بالنسبة للمفاتيح غير JSON (مثل السلاسل والأرقام والمنطقيات)، يمكنك الإشارة إليها باسم المفتاح مباشرةً.
بالنسبة للمفاتيح التي تخزّن كائنات JSON، استخدم صيغة مسار JSON للوصول إلى القيم المتداخلة.
استنادًا إلى مثال الكيان من القسم السابق، تتضمن تعبيرات التصفية الصالحة:
filter = 'overview == "Great product"' # Non-JSON key
filter = 'words >= 100' # Non-JSON key
filter = 'dynamic_json["nested"]["value"] < 50' # JSON object key
String filter = 'overview == "Great product"';
String filter = 'words >= 100';
String filter = 'dynamic_json["nested"]["value"] < 50';
filter = 'overview == "Great product"' // Non-JSON key
filter = 'words >= 100' // Non-JSON key
filter = 'dynamic_json["nested"]["value"] < 50' // JSON object key
filter := 'overview == "Great product"'
filter := 'words >= 100'
filter := 'dynamic_json["nested"]["value"] < 50'
# restful
export filterOverview='overview == "Great product"'
export filterWords='words >= 100'
export filterNestedValue='dynamic_json["nested"]["value"] < 50'
استرجاع مفاتيح الحقول الديناميكية: لإرجاع مفاتيح الحقول الديناميكية في نتائج البحث أو الاستعلام، يجب عليك تحديدها صراحةً في المعلمة output_fields باستخدام نفس بناء جملة مسار JSON الخاصة بالتصفية:
# Example: Include dynamic field keys in search results
results = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.3, 0.4, 0.5]],
filter=filter, # Filter expression defined earlier
limit=10,
output_fields=[
"overview", # Simple dynamic field key
'dynamic_json["varchar"]' # Nested JSON key
]
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.SearchReq
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
FloatVec queryVector = new FloatVec(new float[]{0.1, 0.2, 0.3, 0.4, 0.5});
SearchReq searchReq = SearchReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(queryVector))
.topK(5)
.filter(filter)
.outputFields(Arrays.asList("overview", "dynamic_json['varchar']"))
.build();
SearchResp searchResp = client.search(searchReq);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const address = "YOUR_CLUSTER_ENDPOINT";
const token = "YOUR_CLUSTER_TOKEN";
const client = new MilvusClient({address, token});
const query_vector = [0.1, 0.2, 0.3, 0.4, 0.5]
const res = await client.search({
collection_name: "my_collection",
data: [query_vector],
limit: 5,
filters: filter,
output_fields: ["overview", "dynamic_json['varchar']"]
})
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "YOUR_CLUSTER_ENDPOINT"
token := "YOUR_CLUSTER_TOKEN"
client, err := client.New(ctx, &client.ClientConfig{
Address: milvusAddr,
APIKey: token,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
queryVector := []float32{0.1, 0.2, 0.3, 0.4, 0.5}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"my_collection", // collectionName
5, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithConsistencyLevel(entity.ClStrong).
WithANNSField("my_vector").
WithFilter(filter).
WithOutputFields("overview", "dynamic_json['varchar']"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
export FILTER='color like "red%" and likes > 50'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"data\": [
[0.1, 0.2, 0.3, 0.4, 0.5]
],
\"annsField\": \"my_vector\",
\"filter\": \"${FILTER}\",
\"limit\": 5,
\"outputFields\": [\"overview\", \"dynamic_json.varchar\"]
}"
لا يتم تضمين مفاتيح الحقول الديناميكية في النتائج افتراضيًا ويجب طلبها صراحةً.
للاطلاع على قائمة كاملة بالمشغلات وتعبيرات التصفية المدعومة، راجع البحث المصفى.
ضع كل ذلك معًا
تكون قد تعلمت الآن كيفية استخدام الحقل الديناميكي لتخزين وفهرسة المفاتيح غير المحددة في المخطط بمرونة. بمجرد إدراج مفتاح الحقل الديناميكي، يمكنك استخدامه تمامًا مثل أي حقل آخر في تعبيرات التصفية - لا حاجة إلى بناء جملة خاص.
لإكمال سير العمل في تطبيق واقعي، ستحتاج أيضًا إلى:
إنشاء فهرس على الحقل المتجه الخاص بك (إلزامي لكل مجموعة)
الرجوع إلى تعيين معلمات الفهرس
تحميل المجموعة
ارجع إلى تحميل وتحرير
البحث أو الاستعلام باستخدام مرشحات مسار JSON
الأسئلة الشائعة
متى يجب تحديد حقل بشكل صريح في المخطط بدلاً من استخدام مفتاح حقل ديناميكي؟
يجب عليك تعريف حقل بشكل صريح في المخطط بدلاً من استخدام مفتاح حقل ديناميكي عندما:
يتم تضمين الحقل بشكل متكرر في حقول_المخرجات: يتم ضمان إمكانية استرجاع الحقول المحددة صراحةً فقط بكفاءة من خلال
output_fields. لا يتم تحسين مفاتيح الحقول الديناميكية للاسترجاع عالي التردد وقد تتكبد نفقات أداء زائدة.يتم الوصول إلى الحقل أو تصفيته بشكل متكرر: في حين أن فهرسة مفتاح الحقل الديناميكي يمكن أن يوفر أداء تصفية مماثل لحقول المخطط الثابتة، فإن الحقول المحددة صراحةً توفر بنية أوضح وقابلية صيانة أفضل.
تحتاج إلى تحكم كامل في سلوك الحقل: تدعم الحقول الصريحة القيود على مستوى المخطط والتحقق من الصحة والكتابة بشكل أوضح، والتي يمكن أن تكون مفيدة لإدارة تكامل البيانات واتساقها.
تريد تجنب التناقضات في الفهرسة: تكون البيانات في مفاتيح الحقول الديناميكية أكثر عرضة لعدم الاتساق في النوع أو البنية. يساعد استخدام مخطط ثابت على ضمان جودة البيانات، خاصةً إذا كنت تخطط لاستخدام الفهرسة أو الصب.
هل يمكنني إنشاء فهارس متعددة على نفس مفتاح الحقل الديناميكي بأنواع بيانات مختلفة؟
لا، يمكنك إنشاء فهرس واحد فقط لكل مسار JSON. حتى إذا كان مفتاح الحقل الديناميكي يحتوي على قيم من أنواع مختلطة (على سبيل المثال، بعض السلاسل وبعض الأرقام)، يجب عليك اختيار فهرس واحد json_cast_type عند فهرسة هذا المسار. الفهارس المتعددة على نفس المفتاح بأنواع مختلفة غير مدعومة في الوقت الحالي.
عند فهرسة مفتاح حقل ديناميكي، ماذا لو فشل صب البيانات؟
إذا أنشأت فهرسًا على مفتاح حقل ديناميكي وفشل صب البيانات - على سبيل المثال، إذا كانت القيمة التي من المفترض أن يتم صبها إلى double هي سلسلة غير رقمية مثل "abc"- فسيتم تخطي هذه القيم المحددة بصمت أثناء إنشاء الفهرس. لن تظهر في الفهرس وبالتالي لن يتم إرجاعها في نتائج البحث المستندة إلى التصفية أو نتائج الاستعلام التي تعتمد على الفهرس.
هذا له بعض الآثار المهمة:
لا رجوع إلى الفحص الكامل: إذا تمت فهرسة غالبية الكيانات بنجاح، فإن استعلامات التصفية ستعتمد بالكامل على الفهرس. سيتم استبعاد الكيانات التي فشلت في الفهرسة من مجموعة النتائج - حتى لو كانت تتطابق منطقياً مع شرط التصفية.
مخاطر دقة البحث: في مجموعات البيانات الكبيرة التي تكون فيها جودة البيانات غير متناسقة (خاصةً في مفاتيح الحقول الديناميكية)، يمكن أن يؤدي هذا السلوك إلى نتائج مفقودة غير متوقعة. من المهم ضمان تنسيق بيانات متناسق وصالح قبل الفهرسة.
استخدم دوال الإرسال بحذر: إذا كنت تستخدم
json_cast_functionلتحويل السلاسل إلى أرقام أثناء الفهرسة، تأكد من أن قيم السلسلة قابلة للتحويل بشكل موثوق. سيؤدي عدم التطابق بينjson_cast_typeوالنوع المحول الفعلي إلى حدوث أخطاء أو تخطي الإدخالات.
ماذا يحدث إذا كان الاستعلام الخاص بي يستخدم نوع بيانات مختلف عن نوع البيانات المفهرس المُحَوَّل؟
إذا كان استعلامك يقارن مفتاح حقل ديناميكي باستخدام نوع بيانات مختلف عما تم استخدامه في الفهرس (على سبيل المثال، الاستعلام بمقارنة سلسلة عندما تم إرسال الفهرس إلى double)، فلن يستخدم النظام الفهرس، وقد يعود إلى الفحص الكامل فقط إذا كان ذلك ممكنًا. للحصول على أفضل أداء ودقة، تأكد من تطابق نوع الاستعلام الخاص بك مع json_cast_type المستخدم أثناء إنشاء الفهرس.