ベクトル検索の基礎
ベクトル埋め込みのソート順を記録したインデックスファイルに基づき、近似最近傍探索(ANN 検索)は、受信した検索リクエストに含まれるクエリベクトルに基づいてベクトル埋め込みのサブセットを特定し、クエリベクトルと該サブグループ内のベクトルを比較して、最も類似性の高い結果を返します。ANN 検索により、Zilliz Cloud は効率的な検索体験を提供します。このページでは、基本的な ANN 検索の実行方法について説明します。
コレクション作成後に動的に新しいフィールドを追加した場合、これらのフィールドを含む検索では、値が明示的に設定されていないエンティティに対して、定義されたデフォルト値または NULL が返されます。詳細については、「既存のコレクションへのフィールドの追加」をご覧ください。
概要
ANN 検索と k-最近傍(kNN)検索は、ベクトル類似性検索において一般的な手法です。kNN 検索では、最も類似性の高いベクトルを特定する前に、検索リクエストに含まれるクエリベクトルとベクトル空間内のすべてのベクトルを比較する必要があり、時間とリソースを大量に消費します。
kNN 検索とは異なり、ANN 検索アルゴリズムはベクトル埋め込みのソート順を記録したインデックスファイルを必要とします。検索リクエストが届くと、インデックスファイルを参照して、クエリベクトルに最も類似している可能性のあるベクトル埋め込みを含むサブグループを迅速に特定できます。その後、指定されたメトリックタイプを使用してクエリベクトルとサブグループ内のベクトルとの類似性を測定し、クエリベクトルとの類似性に基づいてグループメンバーをソートして、トップ Kのグループメンバーを特定します。
ANN 検索は事前構築されたインデックスに依存しており、選択するインデックスタイプによって検索スループット、メモリ使用量、検索精度が異なる場合があります。検索パフォーマンスと精度のバランスを取る必要があります。
学習曲線を緩やかにするため、Zilliz Cloud はAUTOINDEXを提供しています。AUTOINDEXを使用すると、Zilliz Cloud はインデックス構築中にコレクション内のデータ分布を分析し、その分析に基づいて最適なインデックスパラメータを設定することで、検索パフォーマンスと精度のバランスを取ります。
AUTOINDEX および適用可能なメトリックタイプの詳細については、「AUTOINDEX の解説」および「メトリックタイプ」をご覧ください。このセクションでは、以下のトピックに関する詳細情報を確認できます。
単一ベクトル検索
ANN 検索において、単一ベクトル検索とは、クエリベクトルが 1 つのみ含まれる検索を指します。事前構築されたインデックスと検索リクエストに含まれるメトリックタイプに基づき、Zilliz Cloud はクエリベクトルに最も類似したトップ K のベクトルを検出します。
このセクションでは、単一ベクトル検索の実行方法について説明します。検索リクエストには単一のクエリベクトルが含まれており、Zilliz Cloud に対して内積(IP)を使用してクエリベクトルとコレクション内のベクトルとの類似性を計算し、最も類似性の高い 3 つの結果を返すよう指示します。
- Python
- Java
- Go
- NodeJS
- cURL
from pymilvus import MilvusClient
client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)
# 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("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.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 := "YOUR_CLUSTER_ENDPOINT"
token := "YOUR_CLUSTER_TOKEN"
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 = "YOUR_CLUSTER_ENDPOINT";
const token = "YOUR_CLUSTER_TOKEN";
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="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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 は、検索結果をクエリベクトルとの類似度スコアに基づいて降順にランキングします。この類似度スコアはクエリベクトルへの距離とも呼ばれ、その値の範囲は使用中のメトリックタイプによって異なります。
次の表は、適用可能なメトリックタイプと対応する距離の範囲を示しています。
メトリックタイプ | Characteristics | Distance Range |
|---|---|---|
| A smaller value indicates a higher similarity. | [0, ∞) |
| A greater value indicates a higher similarity. | [-1, 1] |
| A greater value indicates a higher similarity. | [-1, 1] |
| A smaller value indicates a higher similarity. | [0, 1] |
| A smaller value indicates a higher similarity. | [0, dim(vector)] |
Bulk-Vector Search
同様に、検索リクエストに複数のクエリベクトルを含めることができます。Zilliz Cloud はこれらのクエリベクトルに対して並列で ANN 検索を実行し、2 組の結果を返します。
- Python
- Java
- Go
- NodeJS
- cURL
# 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="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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]
# }
Primary-キー Search
クエリベクトルを設定する代わりに、クエリベクトルがすでにターゲットコレクションに存在している場合、プライマリキーを使用できます。
- Python
- Java
- NodeJS
- Go
- cURL
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 "YOUR_CLUSTER_ENDPOINT/v2/vectordb/entities/search" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_CLUSTER_TOKEN" \
-d '{
"collectionName": "quick_setup",
"annsField": "vector",
"ids": [551, 296, 43],
"limit": 3,
"searchParams": {
"metric_type": "IP"
}
}'
パーティション内でのANN検索
コレクション内に複数のパーティションを作成している場合、検索範囲を特定のパーティションに限定できます。その場合は、検索リクエストにターゲットとなるパーティション名を指定することで、検索範囲をそのパーティション内に制限できます。検索対象のパーティション数を減らすことで、検索パフォーマンスが向上します。
以下のコードスニペットでは、コレクション内に PartitionA という名前のパーティションが存在することを前提としています。
- Python
- Java
- Go
- NodeJS
- cURL
# 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="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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]
# }
出力フィールドの使用
検索結果において、Zilliz Cloud はデフォルトで、上位 K 件のベクトル埋め込みを含むエンティティの主キーと類似度距離(またはスコア)を返します。検索リクエストに目的のフィールド名(ベクトルフィールドおよびスカラーフィールドの両方を含む)を出力フィールドとして指定することで、これらのエンティティに含まれる他のフィールドの値も検索結果に含めることができます。
- Python
- Java
- Go
- NodeJS
- cURL
# 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="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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 が、検索結果に含めるエンティティの数を決定することに気づくかもしれません。このパラメータは、1回の検索で返されるエンティティの最大数を指定するものであり、通常 top-K と呼ばれます。
ページネーション付きのクエリを実行したい場合は、複数の Search リクエストをループで送信し、各クエリリクエストに 制限 および オフセット パラメータを含めることができます。具体的には、現在のクエリ結果に含めたいエンティティ数を 制限 パラメータに設定し、すでに返されたエンティティの総数を オフセット に設定します。
以下の表は、一度に100件のエンティティを返すページネーションクエリにおける 制限 および オフセット パラメータの設定方法を示しています。
クエリ | 1回のクエリで返すエンティティ数 | これまでに返されたエンティティの総数 |
|---|---|---|
1回目のクエリ | 100 | 0 |
2回目のクエリ | 100 | 100 |
3回目のクエリ | 100 | 200 |
n回目のクエリ | 100 | 100 x (n-1) |
なお、1回の ANN 検索における limit と offset の合計値は 16,384 未満である必要があります。
- Python
- Java
- Go
- NodeJS
- cURL
# 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="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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
}'
Use Level
ANN検索を最適化するために、Zilliz Cloudはlevelというパラメータを提供しており、これにより簡略化された検索最適化で検索精度を制御できます。
このパラメータの範囲は1から10で、デフォルト値は1です。値を大きくすると検索の再現率(recall rate)が向上しますが、検索パフォーマンスは低下します。一般的なケースでは、デフォルト値で最大90%の再現率が得られます。必要に応じてこの値を増やすことができます。
level パラメータは現在パブリックプレビュー中です。もし5より大きい値を設定できない場合、ご利用のクラスタはこの機能を完全にはサポートしていない可能性があります。回避策として、代わりに1から5の範囲内の値を設定するか、Zilliz Cloud サポートまでお問い合わせください。
- Python
- Java
- Go
- NodeJS
- cURL
# 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={
"params": {
"level": 10 # The precision control
}
}
)
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});
Map<String, Object> params = new HashMap<>();
params.put("level", 10);
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.topK(3)
.searchParams(params)
.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)
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").
WithSearchParam("level", "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,
params: {
"level": 10 // The precision control
}
})
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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,
"searchParams":{
"params":{
"level":10
}
}
}'
# {"code":0,"cost":0,"data":[{"distance":1,"id":0},{"distance":0.6290165,"id":1},{"distance":0.5975797,"id":4},{"distance":0.9999999,"id":1},{"distance":0.7408552,"id":7},{"distance":0.6290165,"id":0}],"topks":[3]}
Get Recall Rate
level パラメータを調整する際に enable_recall_calculation を true に設定することで、異なる level 値を使用した検索の精度を評価できます。
enable_recall_calculation パラメータは現在パブリックプレビュー中であり、互換性の問題により使用できない場合があります。ご不明な点がございましたら、Zilliz Cloud サポートまでお問い合わせください。
- Python
- Java
- Go
- NodeJS
- cURL
# 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={
"params": {
"level": 10 # The precision control,
"enable_recall_calculation": True # Ask to return recall rate
}
}
)
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});
Map<String, Object> params = new HashMap<>();
params.put("level", 10);
params.put("enable_recall_calculation", true)
SearchReq searchReq = SearchReq.builder()
.collectionName("quick_setup")
.data(Collections.singletonList(queryVector))
.topK(3)
.searchParams(params)
.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)
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").
WithSearchParam("enable_recall_calculation", "true"))
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,
params: {
"level": 10 // The precision control
"enable_recall_calculation": true // Ask to return recall rate
}
})
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
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,
"searchParams":{
"params":{
"level":10,
"enable_recall_calculation": true
}
}
}'
# {"code":0,"cost":0,"data":[{"distance":1,"id":0},{"distance":0.6290165,"id":1},{"distance":0.5975797,"id":4},{"distance":0.9999999,"id":1},{"distance":0.7408552,"id":7},{"distance":0.6290165,"id":0}],"topks":[3]}
検索時に一時的にタイムゾーンを設定する
コレクションに TIMESTAMPTZ フィールドが含まれている場合、検索呼び出し時に timezone パラメータを設定することで、単一の操作に対してデータベースまたはコレクションのデフォルトタイムゾーンを一時的に上書きできます。これにより、その操作中に TIMESTAMPTZ 値の表示方法や比較方法が制御されます。
timezone の値は、有効な IANA タイムゾーン識別子(例:Asia/Shanghai、America/Chicago、UTC など)である必要があります。TIMESTAMPTZ フィールドの使用方法の詳細については、TIMESTAMPTZ フィールド を参照してください。
以下の例では、検索操作時に一時的にタイムゾーンを設定する方法を示しています:
- Python
- Java
- NodeJS
- Go
- cURL
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 "YOUR_CLUSTER_ENDPOINT/v2/vectordb/entities/search" \
-H "Content-Type: application/json" \
-d '{
"collectionName": "quick_setup",
"annsField": "vector",
"data": ['"$QUERY_VECTOR"'],
"limit": 3,
"searchParams": {
"metric_type": "IP",
"timezone": "America/Havana"
}
}'
ANN検索の強化
AUTOINDEXはANN検索の学習曲線を大幅に緩やかにします。ただし、top-Kが大きくなるにつれて検索結果が常に正確であるとは限りません。検索範囲を縮小し、検索結果の関連性を向上させ、検索結果の多様性を高めることで、Zilliz Cloudは以下の検索強化機能を提供しています。
-
フィルター検索
検索リクエストにフィルター条件を含めることで、Zilliz CloudはANN検索を実行する前にメタデータフィルタリングを実施し、検索範囲をコレクション全体から指定されたフィルター条件に一致するエンティティのみに絞り込むことができます。
メタデータフィルタリングおよびフィルター条件の詳細については、Filtered Search および Filtering を参照してください。
-
範囲検索(Range Search)
返されるエンティティの距離またはスコアを特定の範囲内に制限することで、検索結果の関連性を向上させることができます。Zilliz Cloudでは、範囲検索はクエリベクトルと最も類似したベクトル埋め込みを中心とする2つの同心円を描くもので、検索リクエストで両方の円の半径を指定すると、Zilliz Cloudは外側の円内にありながら内側の円外にあるすべてのベクトル埋め込みを返します。
範囲検索の詳細については、Range Search を参照してください。
-
グループ化検索(Grouping Search)
返されたエンティティがある特定のフィールドにおいて同じ値を持つ場合、検索結果はベクトル空間内の全ベクトル埋め込みの分布を十分に反映しない可能性があります。検索結果の多様性を高めるには、グループ化検索をご検討ください。
グループ化検索の詳細については、Grouping Search を参照してください。
-
ハイブリッド検索(Hybrid Search)
コレクションには、異なる埋め込みモデルを使って生成されたベクトル埋め込みを保存するための複数のベクトルフィールドを含めることができます。これにより、これらのベクトルフィールドからの検索結果をハイブリッド検索で再ランキングし、再現率(recall rate)を向上させることが可能です。
ハイブリッド検索の詳細については、Hybrid Search を参照してください。
コレクションに設定可能なベクトルフィールド数の制限については、Zilliz Cloud 制限s を参照してください。
-
検索イテレータ(Search Iterator)
1回のANN検索では最大16,384件のエンティティしか返されません。1回の検索でそれ以上のエンティティが必要な場合は、検索イテレータをご利用ください。
検索イテレータの詳細については、Search Iterator を参照してください。
-
全文検索(全文検索)
全文検索は、テキストデータセット内で特定の単語やフレーズを含むドキュメントを取得し、関連性に基づいて結果をランキングする機能です。この機能により、セマンティック検索の限界(正確な用語を見逃す可能性がある点)を克服し、最も正確かつ文脈に即した結果を得ることができます。また、ベクトル検索を簡素化し、生のテキスト入力をそのまま受け入れ、手動でベクトル埋め込みを生成することなく、テキストデータを自動的にスパース埋め込みに変換します。
全文検索の詳細については、Full Text Search を参照してください。
-
テキストマッチ(Text Match)
Zilliz Cloudのキーワードマッチ機能は、特定の用語に基づいて正確なドキュメントを取得できます。この機能は主にフィルター検索で特定の条件を満たすために使用され、スカラーフィルタリングを組み合わせてクエリ結果をさらに絞り込むことができ、スカラー条件を満たすベクトル内での類似性検索を可能にします。
キーワードマッチの詳細については、キーword Match を参照してください。
-
パーティションキーの使用(Use パーティションキー)
メタデータフィルタリングに複数のスカラーフィールドを含めたり、非常に複雑なフィルター条件を使用したりすると、検索効率に影響を与える可能性があります。スカラーフィールドをパーティションキーとして設定し、検索リクエストでそのパーティションキーを含むフィルター条件を使用すれば、指定されたパーティションキーの値に対応するパーティション内に検索範囲を限定することができます。
パーティションキーの詳細については、Use パーティションキー を参照してください。
-
mmapの使用(Use mmap)
mmap設定の詳細については、Use mmap を参照してください。