البحث المتجهي الأساسي
استنادًا إلى ملف فهرس يسجل الترتيب المصنف لتضمينات المتجهات، يحدد البحث عن أقرب الجيران التقريبي (ANN) مجموعة فرعية من تضمينات المتجهات بناءً على متجه الاستعلام الوارد في طلب البحث المستلم، ويقارن متجه الاستعلام مع تلك الموجودة في المجموعة الفرعية، ويعرض النتائج الأكثر تشابهًا. بفضل البحث ANN، يوفر Milvus تجربة بحث فعالة. تساعدك هذه الصفحة على تعلم كيفية إجراء عمليات البحث الأساسية باستخدام ANN.
إذا أضفت حقولًا جديدة بعد إنشاء المجموعة، فإن عمليات البحث التي تتضمن هذه الحقول تعرض القيم الافتراضية المحددة أو « NULL » (لم يتم تعيين القيمة) للكيانات التي لم يتم تعيين قيم لها صراحةً. لمزيد من التفاصيل، راجع «تعديل مخطط المجموعة».
نظرة عامة
يُعد كل من البحث باستخدام الشبكة العصبية الاصطناعية (ANN) والبحث باستخدام أقرب k جيران (kNN) من الطرق المعتادة في عمليات البحث عن التشابه بين المتجهات. في البحث باستخدام kNN، يجب مقارنة جميع المتجهات في الفضاء المتجهي بمتجه الاستعلام الوارد في طلب البحث قبل تحديد المتجهات الأكثر تشابهًا، وهو ما يستغرق وقتًا طويلاً ويستهلك موارد كثيرة.
على عكس عمليات البحث kNN، تطلب خوارزمية البحث ANN ملف فهرس يسجل الترتيب المصنف لتضمينات المتجهات. عند وصول طلب بحث، يمكنك استخدام ملف الفهرس كمرجع لتحديد موقع مجموعة فرعية تحتوي على الأرجح على تضمينات متجهات هي الأكثر تشابهًا مع متجه الاستعلام بسرعة. بعد ذلك، يمكنك استخدام نوع المقياس المحدد لقياس التشابه بين متجه الاستعلام والمتجهات الموجودة في المجموعة الفرعية، وفرز عناصر المجموعة بناءً على التشابه مع متجه الاستعلام، وتحديد أفضل K عناصر في المجموعة.
تعتمد عمليات البحث باستخدام الشبكات العصبية الاصطناعية (ANN) على الفهارس المعدة مسبقًا، وقد تختلف سرعة البحث واستخدام الذاكرة ودقة البحث باختلاف أنواع الفهارس التي تختارها. تحتاج إلى تحقيق التوازن بين أداء البحث ودقته.
لتقليل منحنى التعلم، يوفر Milvus ميزة AUTOINDEX. باستخدام AUTOINDEX، يمكن لـ Milvus تحليل توزيع البيانات داخل مجموعتك أثناء إنشاء الفهرس، وتعيين معلمات الفهرس الأكثر تحسينًا بناءً على التحليل لتحقيق التوازن بين أداء البحث ودقته.
في هذا القسم، ستجد معلومات تفصيلية حول الموضوعات التالية:
البحث أحادي المتجه
في عمليات البحث باستخدام الشبكات العصبية الاصطناعية (ANN)، يشير البحث أحادي المتجه إلى عملية بحث تتضمن متجه استعلام واحد فقط. استنادًا إلى الفهرس المُعد مسبقًا ونوع المقياس الوارد في طلب البحث، سيقوم Milvus بالعثور على أفضل K متجهات هي الأكثر تشابهًا مع متجه الاستعلام.
في هذا القسم، ستتعلم كيفية إجراء بحث أحادي المتجه. يحتوي طلب البحث على متجه استعلام واحد ويطلب من Milvus استخدام الحاصل الداخلي (IP) لحساب التشابه بين متجهات الاستعلام والمتجهات الموجودة في المجموعة، ثم يعرض المتجهات الثلاثة الأكثر تشابهًا.
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
# 4. Single vector search
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="quick_setup",
anns_field="vector",
data=[query_vector],
limit=3,
search_params={"metric_type": "IP"}
)
for hits in res:
for hit in hits:
print(hit)
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {}
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {}
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {}
# }
# ]
# ]
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;
import java.util.*;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.token("root:Milvus")
.build());
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.annsField("vector")
.topK(3)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output
// TopK results:
// SearchResp.SearchResult(entity={}, score=0.95944905, id=5)
// SearchResp.SearchResult(entity={}, score=0.8689616, id=1)
// SearchResp.SearchResult(entity={}, score=0.866088, id=7)
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 := "localhost:19530"
token := "root:Milvus"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
APIKey: token,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("vector"))
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)
}
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const address = "http://localhost:19530";
const token = "root:Milvus";
const client = new MilvusClient({address, token});
// 4. Single vector search
var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = await client.search({
collection_name: "quick_setup",
data: query_vector,
limit: 3, // The number of results to return
})
console.log(res.results)
// [
// { score: 0.08821295201778412, id: '551' },
// { score: 0.0800950899720192, id: '296' },
// { score: 0.07794742286205292, id: '43' }
// ]
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3
}'
# {
# "code": 0,
# "data": [
# {
# "distance": 0.08821295201778412,
# "id": 551
# },
# {
# "distance": 0.0800950899720192,
# "id": 296
# },
# {
# "distance": 0.07794742286205292,
# "id": 43
# }
# ]
# }
يقوم Milvus بترتيب نتائج البحث حسب درجات التشابه مع متجه الاستعلام بترتيب تنازلي. تُعرف درجة التشابه أيضًا باسم المسافة إلى متجه الاستعلام، وتتنوع قيمها وفقًا لأنواع المقاييس المستخدمة.
يسرد الجدول التالي أنواع المقاييس القابلة للتطبيق ونطاقات المسافة المقابلة لها.
نوع المقياس |
الخصائص |
نطاق المسافة |
|---|---|---|
|
تشير القيمة الأصغر إلى تشابه أعلى. |
[0، ∞) |
|
تشير القيمة الأكبر إلى تشابه أعلى. |
[-1، 1] |
|
تشير القيمة الأكبر إلى تشابه أعلى. |
[-1, 1] |
|
تشير القيمة الأصغر إلى تشابه أعلى. |
[0, 1] |
|
تشير القيمة الأصغر إلى تشابه أعلى. |
[0، dim(vector)] |
البحث عن المتجهات المجمعة
وبالمثل، يمكنك تضمين متجهات استعلام متعددة في طلب البحث. سيقوم Milvus بإجراء عمليات بحث باستخدام الشبكات العصبية الاصطناعية (ANN) لمتجهات الاستعلام بشكل متوازٍ وإرجاع مجموعتين من النتائج.
# 7. Search with multiple vectors
# 7.1. Prepare query vectors
query_vectors = [
[0.041732933, 0.013779674, -0.027564144, -0.013061441, 0.009748648],
[0.0039737443, 0.003020432, -0.0006188639, 0.03913546, -0.00089768134]
]
# 7.2. Start search
res = client.search(
collection_name="quick_setup",
data=query_vectors,
limit=3,
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)
# Output
#
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {}
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {}
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {}
# }
# ],
# [
# {
# "id": 730,
# "distance": 0.04431751370429993,
# "entity": {}
# },
# {
# "id": 333,
# "distance": 0.04231833666563034,
# "entity": {}
# },
# {
# "id": 232,
# "distance": 0.04221535101532936,
# "entity": {}
# }
# ]
# ]
import io.milvus.v2.service.vector.request.SearchReq
import io.milvus.v2.service.vector.request.data.BaseVector;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp
List<BaseVector> queryVectors = Arrays.asList(
new FloatVec(new float[]{0.041732933f, 0.013779674f, -0.027564144f, -0.013061441f, 0.009748648f}),
new FloatVec(new float[]{0.0039737443f, 0.003020432f, -0.0006188639f, 0.03913546f, -0.00089768134f})
);
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(queryVectors)
.topK(3)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output
// TopK results:
// SearchResp.SearchResult(entity={}, score=0.49548206, id=1)
// SearchResp.SearchResult(entity={}, score=0.320147, id=3)
// SearchResp.SearchResult(entity={}, score=0.107413776, id=6)
// TopK results:
// SearchResp.SearchResult(entity={}, score=0.5678123, id=6)
// SearchResp.SearchResult(entity={}, score=0.32368967, id=2)
// SearchResp.SearchResult(entity={}, score=0.24108477, id=3)
queryVectors := []entity.Vector{
entity.FloatVector([]float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}),
entity.FloatVector([]float32{0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104}),
}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
queryVectors,
).WithConsistencyLevel(entity.ClStrong).
WithANNSField("vector"))
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)
}
// 7. Search with multiple vectors
const query_vectors = [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
[0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104]
]
res = await client.search({
collection_name: "quick_setup",
vectors: query_vectors,
limit: 3,
})
console.log(res.results)
// Output
//
// [
// [
// { score: 0.08821295201778412, id: '551' },
// { score: 0.0800950899720192, id: '296' },
// { score: 0.07794742286205292, id: '43' }
// ],
// [
// { score: 0.04431751370429993, id: '730' },
// { score: 0.04231833666563034, id: '333' },
// { score: 0.04221535101532936, id: '232' },
// ]
// ]
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
[0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104]
],
"annsField": "vector",
"limit": 3
}'
# {
# "code": 0,
# "data": [
# [
# {
# "distance": 0.08821295201778412,
# "id": 551
# },
# {
# "distance": 0.0800950899720192,
# "id": 296
# },
# {
# "distance": 0.07794742286205292,
# "id": 43
# }
# ],
# [
# {
# "distance": 0.04431751370429993,
# "id": 730
# },
# {
# "distance": 0.04231833666563034,
# "id": 333
# },
# {
# "distance": 0.04221535101532936,
# "id": 232
# }
# ]
# ],
# "topks":[3]
# }
البحث باستخدام المفتاح الأساسيCompatible with Milvus 2.6.9+
بدلاً من تعيين متجهات الاستعلام، يمكنك استخدام المفاتيح الأساسية إذا كانت متجهات الاستعلام موجودة بالفعل في المجموعة المستهدفة.
res = client.search(
collection_name="quick_setup",
anns_field="vector",
ids=[551, 296, 43],
limit=3,
search_params={"metric_type": "IP"}
)
for hits in res:
for hit in hits:
print(hit)
// java
// node.js
// go
# restful
curl -X POST "http://localhost:19530/v2/vectordb/entities/search" \
-H "Content-Type: application/json" \
-H "Request-Timeout: 10" \
-H "Authorization: Bearer root:Milvus" \
-d '{
"collectionName": "quick_setup",
"annsField": "vector",
"ids": [551, 296, 43],
"limit": 3,
"searchParams": {
"metric_type": "IP"
}
}'
البحث باستخدام الشبكة العصبية الاصطناعية (ANN) في القسم
لنفترض أنك أنشأت أقسامًا متعددة في مجموعة، ويمكنك تضييق نطاق البحث ليشمل عددًا محددًا من الأقسام. في هذه الحالة، يمكنك تضمين أسماء الأقسام المستهدفة في طلب البحث لتقييد نطاق البحث ضمن الأقسام المحددة. يؤدي تقليل عدد الأقسام المشمولة في البحث إلى تحسين أداء البحث.
يفترض مقتطف الشفرة التالي وجود قسم باسم PartitionA في مجموعتك.
# 4. Single vector search
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
res = client.search(
collection_name="quick_setup",
partition_names=["partitionA"],
data=[query_vector],
limit=3,
)
for hits in res:
print("TopK results:")
for hit in hits:
print(hit)
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {}
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {}
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {}
# }
# ]
# ]
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
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.partitionNames(Collections.singletonList("partitionA"))
.data(Collections.singletonList(queryVector))
.topK(3)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output
// TopK results:
// SearchResp.SearchResult(entity={}, score=0.6395302, id=13)
// SearchResp.SearchResult(entity={}, score=0.5408028, id=12)
// SearchResp.SearchResult(entity={}, score=0.49696884, id=17)
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithConsistencyLevel(entity.ClStrong).
WithPartitions("partitionA").
WithANNSField("vector"))
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)
}
// 4. Single vector search
var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = await client.search({
collection_name: "quick_setup",
partition_names: ["partitionA"],
data: query_vector,
limit: 3, // The number of results to return
})
console.log(res.results)
// [
// { score: 0.08821295201778412, id: '551' },
// { score: 0.0800950899720192, id: '296' },
// { score: 0.07794742286205292, id: '43' }
// ]
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "quick_setup",
"partitionNames": ["partitionA"],
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3
}'
# {
# "code": 0,
# "data": [
# {
# "distance": 0.08821295201778412,
# "id": 551
# },
# {
# "distance": 0.0800950899720192,
# "id": 296
# },
# {
# "distance": 0.07794742286205292,
# "id": 43
# }
# ],
# "topks":[3]
# }
استخدام حقول الإخراج
في نتيجة البحث، يقوم Milvus تضمين قيم الحقول الأساسية ومسافات/درجات التشابه للكيانات التي تحتوي على أفضل K تضمينات متجهة بشكل افتراضي. يمكنك تضمين أسماء الحقول المستهدفة، بما في ذلك الحقول المتجهة والعددية، في طلب البحث كحقول إخراج لجعل نتائج البحث تحمل القيم من الحقول الأخرى في هذه الكيانات.
# 4. Single vector search
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = client.search(
collection_name="quick_setup",
data=[query_vector],
limit=3, # The number of results to return
search_params={"metric_type": "IP"},
output_fields=["color"]
)
print(res)
# [
# [
# {
# "id": 551,
# "distance": 0.08821295201778412,
# "entity": {
# "color": "orange_6781"
# }
# },
# {
# "id": 296,
# "distance": 0.0800950899720192,
# "entity": {
# "color": "red_4794"
# }
# },
# {
# "id": 43,
# "distance": 0.07794742286205292,
# "entity": {
# "color": "grey_8510"
# }
# }
# ]
# ]
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
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.topK(3)
.outputFields(Collections.singletonList("color"))
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output
// TopK results:
// SearchResp.SearchResult(entity={color=black_9955}, score=0.95944905, id=5)
// SearchResp.SearchResult(entity={color=red_7319}, score=0.8689616, id=1)
// SearchResp.SearchResult(entity={color=white_5015}, score=0.866088, id=7)
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithConsistencyLevel(entity.ClStrong).
WithANNSField("vector").
WithOutputFields("color"))
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("color: ", resultSet.GetColumn("color").FieldData().GetScalars())
}
// 4. Single vector search
var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = await client.search({
collection_name: "quick_setup",
data: query_vector,
limit: 3, // The number of results to return
output_fields: ["color"]
})
console.log(res.results)
// [
// { score: 0.08821295201778412, id: '551', entity: {"color": "orange_6781"}},
// { score: 0.0800950899720192, id: '296' entity: {"color": "red_4794"}},
// { score: 0.07794742286205292, id: '43' entity: {"color": "grey_8510"}}
// ]
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3,
"outputFields": ["color"]
}'
# {
# "code": 0,
# "data": [
# {
# "distance": 0.08821295201778412,
# "id": 551,
# "color": "orange_6781"
# },
# {
# "distance": 0.0800950899720192,
# "id": 296,
# "color": "red_4794"
# },
# {
# "distance": 0.07794742286205292,
# "id": 43
# "color": "grey_8510"
# }
# ],
# "topks":[3]
# }
فرز نتائج البحث حسب الحقول القياسيةCompatible with Milvus 3.0.x
بشكل افتراضي، يقوم Milvus بترتيب نتائج البحث حسب درجة تشابهها مع متجه الاستعلام. إذا كنت تريد أن تتبع الكيانات التي يتم إرجاعها ترتيب الحقول القياسية، فأضف order_by_fields إلى طلب البحث.
يحدد كل عنصر في order_by_fields حقلًا عدديًا واتجاهًا للفرز. استخدم "asc" للترتيب التصاعدي أو "desc" للترتيب التنازلي. إذا حذفت order ، فسيقوم Milvus بفرز الحقل بالترتيب التصاعدي.
يقوم المثال التالي بفرز نتائج البحث حسب price من الأقل إلى الأعلى. قم بتضمين حقل الفرز في output_fields إذا كنت ترغب في فحص قيمة الحقل في الاستجابة.
res = client.search(
collection_name="product_catalog",
data=query_vectors,
anns_field="embedding",
limit=20,
output_fields=["id", "price", "rating", "category"],
order_by_fields=[
{"field": "price", "order": "asc"}
],
)
// java
// nodejs
// go
# restful
يمكنك أيضًا الفرز حسب حقول عددية متعددة. يطبق Milvus الحقول بالترتيب الذي تحدده. في المثال التالي، يقوم Milvus بفرز النتائج حسب price بترتيب تصاعدي. بالنسبة للكيانات التي لها نفس price ، يقوم Milvus بعد ذلك بالفرز حسب rating بترتيب تنازلي.
res = client.search(
collection_name="product_catalog",
data=query_vectors,
anns_field="embedding",
limit=20,
output_fields=["id", "price", "rating", "category"],
order_by_fields=[
{"field": "price", "order": "asc"},
{"field": "rating", "order": "desc"},
],
)
// java
// nodejs
// go
# restful
بالنسبة للكيانات التي لها نفس القيم في جميع حقول الترتيب المحددة، يحتفظ Milvus بالترتيب الأصلي وفقًا لدرجة التشابه.
استخدام Limit و Offset
قد تلاحظ أن المعلمة limit المضمنة في طلبات البحث تحدد عدد الكيانات التي سيتم تضمينها في نتائج البحث. تحدد هذه المعلمة الحد الأقصى لعدد الكيانات التي سيتم إرجاعها في عملية بحث واحدة، وعادةً ما يشار إليها باسم top-K.
إذا كنت ترغب في إجراء استعلامات مقسمة إلى صفحات، فيمكنك استخدام حلقة لإرسال طلبات بحث متعددة، مع تضمين المعلمتين Limit و Offset في كل طلب بحث. على وجه التحديد، يمكنك تعيين المعلمة Limit على عدد الكيانات التي تريد تضمينها في نتائج الاستعلام الحالي، وتعيين المعلمة Offset على العدد الإجمالي للكيانات التي تم إرجاعها بالفعل.
يوضح الجدول أدناه كيفية تعيين المعلمتين Limit و Offset للاستعلامات المقسمة إلى صفحات عند إرجاع 100 كيان في المرة الواحدة.
الاستعلامات |
الكيانات المطلوب إرجاعها لكل استعلام |
إجمالي الكيانات التي تم إرجاعها بالفعل |
|---|---|---|
الاستعلام الأول |
100 |
0 |
الاستعلام الثاني |
100 |
100 |
الاستعلام الثالث |
100 |
200 |
الاستعلام رقم n |
100 |
100 × (n-1) |
يرجى ملاحظة أن مجموع limit و offset في عملية بحث واحدة باستخدام الشبكة العصبية الاصطناعية (ANN) يجب أن يكون أقل من 16,384.
# 4. Single vector search
query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = client.search(
collection_name="quick_setup",
data=[query_vector],
limit=3, # The number of results to return
search_params={
"metric_type": "IP",
"offset": 10 # The records to skip
}
)
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
FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.topK(3)
.offset(10)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output
// TopK results:
// SearchResp.SearchResult(entity={}, score=0.24120237, id=16)
// SearchResp.SearchResult(entity={}, score=0.22559784, id=9)
// SearchResp.SearchResult(entity={}, score=-0.09906838, id=2)
queryVector := []float32{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592}
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"quick_setup", // collectionName
3, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithConsistencyLevel(entity.ClStrong).
WithANNSField("vector").
WithOffset(10))
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)
}
// 4. Single vector search
var query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
res = await client.search({
collection_name: "quick_setup",
data: query_vector,
limit: 3, // The number of results to return,
offset: 10 // The record to skip.
})
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3,
"offset": 10
}'
تعيين منطقة زمنية مؤقتًا لعملية بحث
إذا كانت مجموعتك تحتوي على حقل TIMESTAMPTZ ، فيمكنك تجاوز المنطقة الزمنية الافتراضية لقاعدة البيانات أو المجموعة مؤقتًا لعملية واحدة عن طريق تعيين المعلمة timezone في استدعاء البحث. يتحكم هذا في كيفية عرض قيم TIMESTAMPTZ ومقارنتها أثناء العملية.
يجب أن تكون قيمة timezone معرّف منطقة زمنية صالحًا وفقًا لمعايير IANA (على سبيل المثال، Asia/Shanghai أو America/Chicago أو UTC). للحصول على تفاصيل حول كيفية استخدام حقل TIMESTAMPTZ ، راجع حقل TIMESTAMPTZ.
يوضح المثال أدناه كيفية تعيين منطقة زمنية مؤقتًا لعملية بحث:
res = client.search(
collection_name="quick_setup",
anns_field="vector",
data=[query_vector],
limit=3,
search_params={"metric_type": "IP"},
timezone="America/Havana",
)
// java
// js
// go
# restful
export QUERY_VECTOR='[0.1, 0.2, 0.3, 0.4]'
curl -X POST "http://localhost:19530/v2/vectordb/entities/search" \
-H "Content-Type: application/json" \
-H "Request-Timeout: 10" \
-d '{
"collectionName": "quick_setup",
"annsField": "vector",
"data": ['"$QUERY_VECTOR"'],
"limit": 3,
"searchParams": {
"metric_type": "IP",
"timezone": "America/Havana"
}
}'
تحسين البحث في شبكات ANN
تعمل ميزة AUTOINDEX على تسهيل عملية تعلم عمليات البحث باستخدام الشبكات العصبية الاصطناعية (ANN) بشكل كبير. ومع ذلك، قد لا تكون نتائج البحث صحيحة دائمًا مع زيادة عدد النتائج الأولى (top-K). من خلال تقليل نطاق البحث، وتحسين ملاءمة نتائج البحث، وتنويع نتائج البحث، تعمل Milvus على تحقيق التحسينات التالية في عملية البحث.
البحث المُصفى
يمكنك تضمين شروط التصفية في طلب البحث بحيث يقوم Milvus بتصفية البيانات الوصفية قبل إجراء عمليات البحث باستخدام الشبكات العصبية الاصطناعية (ANN)، مما يقلل نطاق البحث من المجموعة بأكملها إلى الكيانات التي تطابق شروط التصفية المحددة فقط.
لمزيد من المعلومات حول تصفية البيانات الوصفية وشروط التصفية، راجع «البحث المُصفى» و«شرح التصفية» والمواضيع ذات الصلة.
البحث في نطاق
يمكنك تحسين ملاءمة نتائج البحث عن طريق تقييد المسافة أو النتيجة للكيانات التي يتم إرجاعها ضمن نطاق محدد. في Milvus، يتضمن البحث في النطاق رسم دائرتين متحدتي المركز مع اعتبار التضمين المتجه الأكثر تشابهًا مع متجه الاستعلام مركزًا لهما. يحدد طلب البحث نصف قطر كلتا الدائرتين، ويقوم Milvus بإرجاع جميع التضمينات المتجهة التي تقع داخل الدائرة الخارجية دون الدائرة الداخلية.
لمزيد من المعلومات حول البحث في النطاق، راجع «البحث في النطاق».
البحث بالتجميع
إذا كانت الكيانات التي يتم إرجاعها تحتوي على نفس القيمة في حقل معين، فقد لا تمثل نتائج البحث توزيع جميع التضمينات المتجهة في الفضاء المتجه. لتنويع نتائج البحث، ضع في اعتبارك استخدام البحث حسب المجموعات.
لمزيد من المعلومات حول البحث بالتجميع، راجع البحث بالتجميع،
البحث الهجين
يمكن أن تتضمن المجموعة حقول متجهات متعددة لحفظ التضمينات المتجهة التي تم إنشاؤها باستخدام نماذج تضمين مختلفة. وبذلك، يمكنك استخدام البحث الهجين لإعادة ترتيب نتائج البحث من حقول المتجهات هذه، مما يؤدي إلى تحسين معدل الاسترجاع.
لمزيد من المعلومات حول البحث الهجين، راجع «البحث الهجين».
مكرر البحث
يعرض البحث الفردي باستخدام الشبكة العصبية الاصطناعية (ANN) ما يصل إلى 16,384 كيانًا كحد أقصى. ضع في اعتبارك استخدام مكررات البحث إذا كنت بحاجة إلى عرض المزيد من الكيانات في عملية بحث واحدة.
للحصول على تفاصيل حول مكررات البحث، راجع مكرر البحث.
البحث عن النص الكامل
البحث عن النص الكامل هو ميزة تسترد المستندات التي تحتوي على مصطلحات أو عبارات محددة في مجموعات بيانات النص، ثم تصنف النتائج بناءً على مدى صلتها بالموضوع. تتغلب هذه الميزة على قيود البحث الدلالي، التي قد تتجاهل المصطلحات الدقيقة، مما يضمن حصولك على النتائج الأكثر دقة وذات الصلة بالسياق. بالإضافة إلى ذلك، فإنها تبسط عمليات البحث المتجهي من خلال قبول إدخال النص الخام، وتحويل بيانات النص تلقائيًا إلى تضمينات متفرقة دون الحاجة إلى إنشاء تضمينات متجهة يدويًّا.
للحصول على تفاصيل حول البحث عن النص الكامل، راجع " البحث عن النص الكامل".
مطابقة النص
تتيح مطابقة الكلمات المفتاحية في Milvus استرجاع المستندات بدقة بناءً على مصطلحات محددة. تُستخدم هذه الميزة بشكل أساسي في البحث المُصفى لتلبية شروط محددة، ويمكنها دمج التصفية القياسية لتحسين نتائج الاستعلام، مما يتيح إجراء عمليات بحث عن التشابه داخل المتجهات التي تستوفي المعايير القياسية.
للحصول على تفاصيل حول مطابقة الكلمات المفتاحية، راجع " مطابقة الكلمات المفتاحية".
استخدام مفتاح التقسيم
قد يؤثر تضمين حقول قياسية متعددة في تصفية البيانات الوصفية واستخدام شرط تصفية معقد إلى حد ما على كفاءة البحث. بمجرد تعيين حقل قياسي كمفتاح التقسيم واستخدام شرط تصفية يتضمن مفتاح التقسيم في طلب البحث، يمكن أن يساعد ذلك في تقييد نطاق البحث ضمن الأقسام المطابقة لقيم مفتاح التقسيم المحددة.
للحصول على تفاصيل حول مفتاح التقسيم، راجع استخدام مفتاح التقسيم.
استخدام mmap
للحصول على تفاصيل حول إعدادات mmap، راجع استخدام mmap.
ضغط التجميع
للحصول على تفاصيل حول عمليات ضغط التجميع، راجع " ضغط التجميع".
استخدام إعادة الترتيب
للحصول على تفاصيل حول استخدام أدوات الترتيب لتحسين ملاءمة نتائج البحث، راجع نظرة عامة على Decay Ranker ونظرة عامة على Model Ranker.