حقول الأرقام
تُستخدم حقول الأرقام لتخزين البيانات الرقمية غير المتجهة في ملفوس. تُستخدم هذه الحقول عادةً لوصف المعلومات الإضافية المتعلقة ببيانات المتجهات، مثل العمر والسعر وما إلى ذلك. باستخدام هذه البيانات، يمكنك وصف المتجهات بشكل أفضل وتحسين كفاءة تصفية البيانات والاستعلامات الشرطية.
تعتبر حقول الأرقام مفيدة بشكل خاص في العديد من السيناريوهات. على سبيل المثال، في توصيات التجارة الإلكترونية، يمكن استخدام حقل السعر للتصفية؛ في تحليل الملف الشخصي للمستخدم، يمكن أن تساعد النطاقات العمرية في تنقيح النتائج. بالاقتران مع البيانات المتجهة، يمكن أن تساعد حقول الأرقام النظام في توفير عمليات بحث متشابهة مع تلبية احتياجات المستخدم الشخصية بدقة أكبر.
أنواع حقول الأرقام المدعومة
يدعم Milvus أنواع حقول أرقام مختلفة لتلبية احتياجات تخزين البيانات والاستعلام المختلفة.
النوع | الوصف |
---|---|
| نوع منطقي لتخزين |
| عدد صحيح 8 بت، مناسب لتخزين البيانات الصحيحة ذات النطاق الصغير. |
| عدد صحيح 16 بت، مناسب لبيانات الأعداد الصحيحة متوسطة المدى. |
| عدد صحيح 32 بت، مثالي لتخزين البيانات الصحيحة العامة مثل كميات المنتجات أو معرّفات المستخدم. |
| عدد صحيح 64 بت، مناسب لتخزين البيانات ذات النطاق الكبير مثل الطوابع الزمنية أو المعرفات. |
| رقم عائم 32 بت، للبيانات التي تتطلب دقة عامة، مثل التصنيفات أو درجة الحرارة. |
| رقم ذو فاصلة عائمة مزدوجة الدقة 64 بت، للبيانات عالية الدقة مثل المعلومات المالية أو الحسابات العلمية. |
إضافة حقل رقم
لاستخدام حقول الأرقام في Milvus، قم بتعريف الحقول ذات الصلة في مخطط المجموعة، مع تعيين datatype
إلى نوع مدعوم مثل BOOL
أو INT8
. للحصول على قائمة كاملة بأنواع حقول الأرقام المدعومة، راجع أنواع حقول الأرقام المدعومة.
يوضح المثال التالي كيفية تعريف مخطط يتضمن حقول الأرقام age
و price
.
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="age", datatype=DataType.INT64)
schema.add_field(field_name="price", datatype=DataType.FLOAT)
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("age")
.dataType(DataType.Int64)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("price")
.dataType(DataType.Float)
.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: "age",
data_type: DataType.Int64,
},
{
name: "price",
data_type: DataType.Float,
},
{
name: "pk",
data_type: DataType.Int64,
is_primary_key: true,
},
{
name: "embedding",
data_type: DataType.FloatVector,
dim: 3,
},
];
export int64Field='{
"fieldName": "age",
"dataType": "Int64"
}'
export floatField='{
"fieldName": "price",
"dataType": "Float"
}'
export pkField='{
"fieldName": "pk",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "embedding",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 3
}
}'
export schema="{
\"autoID\": false,
\"fields\": [
$int64Field,
$floatField,
$pkField,
$vectorField
]
}"
الحقل الأساسي وحقل المتجه إلزاميان عند إنشاء مجموعة. يعرّف الحقل الأساسي كل كيان بشكل فريد، بينما يعد الحقل المتجه ضروريًا للبحث عن التشابه. لمزيد من التفاصيل، راجع الحقل الأساسي والمعرف التلقائي أو المتجه الكثيف أو المتجه الثنائي أو المتجه المتناثر.
تعيين معلمات الفهرس
يعد تعيين معلمات الفهرس لحقول الأرقام أمرًا اختياريًا ولكن يمكن أن يحسن كفاءة الاسترجاع بشكل كبير.
في المثال التالي، نقوم بإنشاء AUTOINDEX
لحقل الرقم age
، مما يسمح لـ Milvus بإنشاء فهرس مناسب تلقائيًا بناءً على نوع البيانات. لمزيد من المعلومات، راجع AUTOINDEX.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="age",
index_type="AUTOINDEX",
index_name="inverted_index"
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
.fieldName("age")
.indexType(IndexParam.IndexType.AUTOINDEX)
.build());
const indexParams = {
index_name: 'inverted_index',
field_name: 'age',
index_type: IndexType.AUTOINDEX,
);
export indexParams='[
{
"fieldName": "age",
"indexName": "inverted_index",
"indexType": "AUTOINDEX"
}
]'
بالإضافة إلى AUTOINDEX
، يمكنك تحديد أنواع فهرس حقول الأرقام الأخرى. لمعرفة أنواع الفهارس المدعومة، راجع الفهارس العددية.
علاوة على ذلك، قبل إنشاء المجموعة، يجب إنشاء فهرس للحقل المتجه. في هذا المثال، نستخدم في هذا المثال AUTOINDEX
لتبسيط إعدادات فهرس المتجه.
# Add vector index
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX", # Use automatic indexing to simplify complex index settings
metric_type="COSINE" # Specify similarity metric type, options include L2, COSINE, or IP
)
indexes.add(IndexParam.builder()
.fieldName("embedding")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE)
.build());
import { IndexType } from "@zilliz/milvus2-sdk-node";
const indexParams = [
{
field_name: "age",
index_name: "inverted_index",
index_type: IndexType.AUTOINDEX,
},
{
field_name: "embedding",
metric_type: "COSINE",
index_type: IndexType.AUTOINDEX,
},
];
export indexParams='[
{
"fieldName": "age",
"indexName": "inverted_index",
"indexType": "AUTOINDEX"
},
{
"fieldName": "embedding",
"metricType": "COSINE",
"indexType": "AUTOINDEX"
}
]'
إنشاء مجموعة
بمجرد تحديد المخطط والفهارس، يمكنك إنشاء مجموعة تتضمن حقول الأرقام.
# Create Collection
client.create_collection(
collection_name="your_collection_name",
schema=schema,
index_params=index_params
)
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_scalar_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
client.create_collection({
collection_name: "my_scalar_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_scalar_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
إدراج البيانات
بعد إنشاء المجموعة، يمكنك إدراج البيانات التي تتضمن حقول الأرقام.
data = [
{"age": 25, "price": 99.99, "pk": 1, "embedding": [0.1, 0.2, 0.3]},
{"age": 30, "price": 149.50, "pk": 2, "embedding": [0.4, 0.5, 0.6]},
{"age": 35, "price": 199.99, "pk": 3, "embedding": [0.7, 0.8, 0.9]},
]
client.insert(
collection_name="my_scalar_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("{\"age\": 25, \"price\": 99.99, \"pk\": 1, \"embedding\": [0.1, 0.2, 0.3]}", JsonObject.class));
rows.add(gson.fromJson("{\"age\": 30, \"price\": 149.50, \"pk\": 2, \"embedding\": [0.4, 0.5, 0.6]}", JsonObject.class));
rows.add(gson.fromJson("{\"age\": 35, \"price\": 199.99, \"pk\": 3, \"embedding\": [0.7, 0.8, 0.9]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_scalar_collection")
.data(rows)
.build());
const data = [
{ age: 25, price: 99.99, pk: 1, embedding: [0.1, 0.2, 0.3] },
{ age: 30, price: 149.5, pk: 2, embedding: [0.4, 0.5, 0.6] },
{ age: 35, price: 199.99, pk: 3, embedding: [0.7, 0.8, 0.9] },
];
client.insert({
collection_name: "my_scalar_collection",
data: data,
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"age": 25, "price": 99.99, "pk": 1, "embedding": [0.1, 0.2, 0.3]},
{"age": 30, "price": 149.50, "pk": 2, "embedding": [0.4, 0.5, 0.6]},
{"age": 35, "price": 199.99, "pk": 3, "embedding": [0.7, 0.8, 0.9]}
],
"collectionName": "my_scalar_collection"
}'
في هذا المثال، نقوم بإدراج البيانات التي تتضمن age
، price
، pk
(الحقل الأساسي)، والتمثيلات المتجهة (embedding
). للتأكد من أن البيانات المدرجة تتطابق مع الحقول المحددة في المخطط، يوصى بالتحقق من أنواع البيانات مسبقًا لتجنب الأخطاء.
إذا قمت بتعيين enable_dynamic_fields=True
عند تعريف المخطط، يسمح لك ميلفوس بإدراج حقول الأرقام التي لم يتم تعريفها مسبقًا. ومع ذلك، ضع في اعتبارك أن هذا قد يزيد من تعقيد الاستعلامات والإدارة، مما قد يؤثر على الأداء. لمزيد من المعلومات، راجع الحقل الديناميكي.
البحث والاستعلام
بعد إضافة حقول الأرقام، يمكنك استخدامها للتصفية في عمليات البحث والاستعلام لتحقيق نتائج بحث أكثر دقة.
تصفية الاستعلامات
بعد إضافة حقول الأرقام، يمكنك استخدامها للتصفية في الاستعلامات. على سبيل المثال، يمكنك الاستعلام عن جميع الكيانات التي يتراوح فيها age
بين 30 و40.
filter = "30 <= age <= 40"
res = client.query(
collection_name="my_scalar_collection",
filter=filter,
output_fields=["age","price"]
)
print(res)
# Output
# data: ["{'age': 30, 'price': np.float32(149.5), 'pk': 2}", "{'age': 35, 'price': np.float32(199.99), 'pk': 3}"]
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
String filter = "30 <= age <= 40";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_scalar_collection")
.filter(filter)
.outputFields(Arrays.asList("age", "price"))
.build());
System.out.println(resp.getQueryResults());
// Output
//
// [QueryResp.QueryResult(entity={price=149.5, pk=2, age=30}), QueryResp.QueryResult(entity={price=199.99, pk=3, age=35})]
client.query({
collection_name: 'my_scalar_collection',
filter: '30 <= age <= 40',
output_fields: ['age', 'price']
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_scalar_collection",
"filter": "30 <= age <= 40",
"outputFields": ["age","price"]
}'
## {"code":0,"cost":0,"data":[{"age":30,"pk":2,"price":149.5},{"age":35,"pk":3,"price":199.99}]}
يُرجع تعبير الاستعلام هذا جميع الكيانات المطابقة ويُخرج حقولها age
و price
. لمزيد من المعلومات حول استعلامات التصفية، راجع تصفية البيانات الوصفية.
البحث المتجه مع تصفية الأرقام
بالإضافة إلى تصفية حقول الأرقام الأساسية، يمكنك دمج عمليات البحث عن التشابه المتجه مع مرشحات حقول الأرقام. على سبيل المثال، يوضح الرمز التالي كيفية إضافة عامل تصفية حقل رقمي إلى بحث متجه.
filter = "25 <= age <= 35"
res = client.search(
collection_name="my_scalar_collection",
data=[[0.3, -0.6, 0.1]],
limit=5,
search_params={"params": {"nprobe": 10}},
output_fields=["age","price"],
filter=filter
)
print(res)
# Output
# data: ["[{'id': 1, 'distance': -0.06000000238418579, 'entity': {'age': 25, 'price': 99.98999786376953}}, {'id': 2, 'distance': -0.12000000476837158, 'entity': {'age': 30, 'price': 149.5}}, {'id': 3, 'distance': -0.18000000715255737, 'entity': {'age': 35, 'price': 199.99000549316406}}]"]
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;
String filter = "25 <= age <= 35";
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_scalar_collection")
.annsField("embedding")
.data(Collections.singletonList(new FloatVec(new float[]{0.3f, -0.6f, 0.1f})))
.topK(5)
.outputFields(Arrays.asList("age", "price"))
.filter(filter)
.build());
System.out.println(resp.getSearchResults());
// Output
//
// [[SearchResp.SearchResult(entity={price=199.99, age=35}, score=-0.19054288, id=3), SearchResp.SearchResult(entity={price=149.5, age=30}, score=-0.20163085, id=2), SearchResp.SearchResult(entity={price=99.99, age=25}, score=-0.2364331, id=1)]]
client.search({
collection_name: 'my_scalar_collection',
data: [0.3, -0.6, 0.1],
limit: 5,
output_fields: ['age', 'price'],
filter: '25 <= age <= 35'
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_scalar_collection",
"data": [
[0.3, -0.6, 0.1]
],
"annsField": "embedding",
"limit": 5,
"outputFields": ["age", "price"]
}'
## {"code":0,"cost":0,"data":[{"age":35,"distance":-0.19054288,"id":3,"price":199.99},{"age":30,"distance":-0.20163085,"id":2,"price":149.5},{"age":25,"distance":-0.2364331,"id":1,"price":99.99}]}
في هذا المثال، نحدد أولًا متجه استعلام ونضيف شرط تصفية 25 <= age <= 35
أثناء البحث. هذا يضمن أن نتائج البحث لا تتشابه مع متجه الاستعلام فحسب، بل تفي أيضًا بالنطاق العمري المحدد. لمزيد من المعلومات، راجع تصفية البيانات الوصفية.