基本ベクトル検索
近似最近傍(ANN)検索は、ベクトル埋込みのソート順を記録したインデックスファイルに基づいて、受信した検索リクエストに含まれるクエリベクトルからベクトル埋込みの部分集合を探し出し、その部分集合内のベクトルとクエリベクトルを比較し、最も類似した結果を返します。ANN検索により、Milvusは効率的な検索体験を提供します。このページでは、基本的なANN検索の方法を説明します。
コレクション作成後に新しいフィールドを動的に追加した場合、これらのフィールドを含む検索は、定義されたデフォルト値または明示的に値が設定されていないエンティティのNULLを返します。詳細は、"Add Fields to an Existing Collection" を参照してください。
概要
ANN および k-Nearest Neighbors (kNN) 検索は、ベクトル類似性検索の通常の手法です。kNN検索では、ベクトル空間内のすべてのベクトルを検索要求で運ばれたクエリ・ベクトルと比較してから、最も似ているものを見つけ出す必要があり、時間とリソースを消費します。
kNN検索とは異なり、ANN検索アルゴリズムは、ベクトルの埋め込み順をソートしたインデックスファイルを要求します。検索要求が来たとき、インデックスファイルを参照として使用することで、クエリ・ベクトルに最も類似したベクトル埋め込みを含むサブグループを素早く見つけることができます。次に、指定されたメトリックタイプを使用して、クエリベクトルとサブグループ内の類似度を測定し、クエリベクトルとの類似度に基づいてグループメンバーをソートし、上位K個のグループメンバーを割り出すことができます。
ANN検索は事前に構築されたインデックスに依存しており、検索スループット、メモリ使用量、検索の正しさは、選択したインデックスタイプによって異なる可能性があります。検索の性能と正しさのバランスをとる必要がある。
Milvusは学習曲線を減らすために、AUTOINDEXを提供しています。AUTOINDEXを使用すると、Milvusはインデックスを構築する際にコレクション内のデータ分布を分析し、その分析に基づいて最も最適化されたインデックスパラメータを設定し、検索性能と正しさのバランスを取ることができます。
このセクションでは、以下のトピックに関する詳細情報をご覧いただけます:
単一ベクトル検索
ANN検索において、単一ベクトル検索とは1つのクエリベクトルのみを含む検索を指す。Milvusは事前に構築されたインデックスと検索要求に含まれるメトリックタイプに基づいて、クエリベクトルに最も類似した上位K個のベクトルを検索します。
このセクションでは、単一ベクトル検索の方法を学びます。検索リクエストは1つのクエリベクトルを運び、MilvusにInner Product (IP)を使ってクエリベクトルとコレクション内のベクトル間の類似度を計算し、最も類似した3つのベクトルを返すよう依頼します。
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" \
-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(ベクトル)]. |
一括ベクトル検索
同様に、検索リクエストに複数のクエリベクトルを含めることができます。milvusはクエリベクトルに対してANN検索を並行して行い、2組の結果を返します。
# 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" \
-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
パーティション内の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" \
-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" \
-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]
# }
Limit と Offset の使用
検索リクエストに含まれるパラメータlimit が、検索結果に含めるエンティティの数を決定していることにお気づきでしょうか。このパラメータは、1回の検索で返すエンティティの最大数を指定するもので、通常はtop-K と呼ばれます。
ページ分割されたクエリを実行したい場合は、ループを使用して複数の Search 要求を送信し、LimitパラメータとOffsetパラメータを各クエリ要求に含めることができます。具体的には、Limitパラメータを現在のクエリ結果に含めたいエンティティの数に設定し、Offsetパラメータをすでに返されたエンティティの総数に設定します。
以下の表は、一度に 100 のエンティティを返すページ分割クエリのLimitおよびOffsetパラメータの設定方法の概要です。
クエリ |
クエリごとに返すエンティティ |
合計で既に返されたエンティティ |
|---|---|---|
最初のクエリ |
100 |
0 |
2回目のクエリー |
100 |
100 |
第3クエリ |
100 |
200 |
n番目のクエリー |
100 |
100 x (n-1) |
なお、1回のANN検索におけるlimit とoffset の合計は、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" \
-d '{
"collectionName": "quick_setup",
"data": [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]
],
"annsField": "vector",
"limit": 3,
"offset": 10
}'
検索にタイムゾーンを一時的に設定する
コレクションにTIMESTAMPTZ フィールドがある場合、検索コールでtimezone パラメータを設定することで、1回の操作でデータベースまたはコレクションのデフォルトタイムゾーンを一時的にオーバーライドできます。これは、操作中に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
ANN検索の強化
AUTOINDEX は ANN 検索の学習曲線をかなり平坦にする。しかし、TOP-Kが大きくなるにつれて、検索結果が必ずしも正しいとは限らない。Milvusは、検索範囲の縮小、検索結果の関連性の向上、検索結果の多様化により、以下のような検索機能の強化を図っている。
フィルタリング検索
MilvusがANN検索を行う前にメタデータのフィルタリングを行い、検索範囲をコレクション全体から指定されたフィルタリング条件に一致するエンティティのみに縮小するように、検索リクエストにフィルタリング条件を含めることができます。
メタデータのフィルタリングとフィルタリング条件の詳細については、フィルタリング検索、フィルタリングの説明、および関連するトピックを参照してください。
範囲検索
特定の範囲内で返されるエンティティの距離またはスコアを制限することにより、検索結果の関連性を向上させることができます。Milvusでは、範囲検索では、クエリベクトルに最も近いベクトル埋め込みを中心として2つの同心円を描きます。検索リクエストは両円の半径を指定し、Milvusは外側の円に含まれ、内側の円に含まれないすべてのベクトル埋め込みを返します。
範囲検索の詳細については、範囲検索を参照してください。
グループ化検索
返されたエンティティが特定のフィールドで同じ値を保持している場合、検索結果はベクトル空間内のすべてのベクトル埋め込み値の分布を表していない可能性があります。検索結果を多様化するには、グルーピング検索の使用を検討する。
グループ化検索の詳細については、グループ化検索を参照してください、
ハイブリッド検索
コレクションは、異なる埋め込みモデルを使用して生成されたベクトル埋め込みを保存するために、複数のベクトルフィールドを含むことができます。そうすることで、ハイブリッド検索を使用して、これらのベクトル・フィールドからの検索結果を再ランク付けし、想起率を向上させることができます。
ハイブリッド検索については、ハイブリッド検索を参照してください。
検索イテレータ
単一の ANN 検索は、最大 16,384 エンティティを返します。1回の検索でより多くのエンティティを返す必要がある場合は、検索イテレータの使用を検討する。
検索イテレータの詳細については、「検索イテレータ」を参照してください。
全文検索
全文検索は、テキストデータセット内の特定の語句を含む文書を検索し、関連性に基づいて結果をランク付けする機能である。この機能は、正確な用語を見落とす可能性のあるセマンティック検索の制限を克服し、最も正確で文脈に関連した結果を確実に受け取ることができます。さらに、生のテキスト入力を受け付けることでベクトル検索を簡素化し、ベクトル埋め込みを手動で生成することなく、テキストデータをスパース埋め込みに自動的に変換します。
全文検索の詳細については、全文検索を参照してください。
テキストマッチ
Milvusのキーワードマッチは、特定の用語に基づいた正確な文書検索を可能にします。この機能は、主に特定の条件を満たすフィルタリング検索に使用され、スカラーフィルタリングを組み込んでクエリ結果を絞り込むことができるため、スカラー条件を満たすベクトル内の類似検索が可能です。
キーワードマッチの詳細については、キーワードマッチを参照してください。
パーティション・キーの使用
複数のスカラー・フィールドをメタデータ・フィルタリングに関与させ、かなり複雑なフィルタリング条件を使用すると、検索効率に影響することがあります。スカラー・フィールドをパーティション・キーに設定し、検索リクエストでパーティション・キーを含むフィルタリング条件を使用すると、指定したパーティション・キーの値に対応するパーティション内に検索範囲を制限することができます。
パーティション・キーの詳細については、「パーティション・キーの使用」を参照してください。
mmapを使用する
mmap-settingsの詳細については、「mmapを使用する」を参照してください。
クラスタリング・コンパクション
クラスタリング・コンパクションの詳細については、クラスタリング・コンパクションを参照してください。
リランキングの使用
検索結果の関連性を高めるためにランカーを使用することについての詳細はDecay Ranker OverviewとModel Ranker Overview を参照してください。