このトピックでは、ベクトルクラスターリコールモードの設定と使用方法について説明します。具体的には、コレクションの作成、バッキングの事前作成、スライス重心の登録、ベクトルデータの書き込み、クエリ時の候補スライスの自動選択、および選択されたスライス内でのベクトル取得の制御について解説します。機能の位置付け、シナリオ、モード選択については、「」をご参照ください。
このモードは、作成パラメーター slice_strategy=vector_cluster によって決定され、コレクション作成後は変更できません。既存のコレクションを別のモードに切り替えるには、新しいコレクションを作成し、データを再度インポートする必要があります。一般的な管理 API とデータ API については、「API リファレンス」をご参照ください。
以下のセクションでは、ワークフローの実行順序に従って説明します。auto_create_slice=false を維持し、スライスの重心を登録してからデータを書き込むという順序制約は必須です。重心を持たないスライスは、候補スライスの自動選択に参加しないため、そのようなスライスに書き込まれたデータは自動的にリコールされることはありません。
コレクションの作成
ベクトルクラスターリコールモードでは、各ベクトルクラスターが 1 つのスライスに対応し、クラスターの重心がそのスライスの重心として登録されます。以下の例では、手動で構築した 3 つのベクトルクラスターを使用してワークフローを検証します。デフォルトでは 2 つの候補スライスがクエリされ、最大で 3 つのスライスをクエリできます。これらの値はこの例にのみ適用されます。本番環境では、実際のクラスタリング結果を使用し、再現率、レイテンシー、リソースオーバーヘッドに基づいて候補スライスの数を決定してください。
PUT /_slice_collection/products
{
"slice_strategy": "vector_cluster",
"auto_create_slice": false,
"settings": {
"index.number_of_shards": 2,
"index.number_of_replicas": 2
},
"mappings": {
"properties": {
"cluster_id": { "type": "keyword" },
"name": { "type": "keyword" },
"embedding": {
"type": "dense_vector",
"dims": 2,
"index": true,
"similarity": "cosine",
"index_options": {
"type": "bbq_disk"
}
}
}
},
"config": {
"routing_field": "cluster_id",
"vector_dims": 2,
"default_query_vector_path": "knn.query_vector",
"default_query_slice_count": 2,
"max_query_slice_count": 3
}
}config は、ベクトルクラスターリコールモードの必須パラメーターです:
config パラメーター | 必須 | 説明 |
routing_field | いいえ | 書き込まれるドキュメントのトップレベルフィールドからスライスを読み取ります。a.b 形式のネストされたパスはサポートされていません。 |
vector_dims | はい | スライス重心のベクトル次元です。有効値は 1 から 4096 です。登録するすべての重心の次元は、この値と一致する必要があります。 |
default_query_vector_path | はい | リクエスト内のクエリベクトルのパスです。有効値は knn.query_vector と knn.N.query_vector です。N は 0 から始まり、knn.query_vector は最初の KNN 句のクエリベクトルと同等です。 |
default_query_slice_count | いいえ | クエリごとの候補スライスのデフォルト数です。デフォルト値は 128 です。有効値は 1 から 10000 です。このパラメーターを max_query_slice_count (デフォルト値: 512) より大きい値に設定する場合は、同じリクエストで max_query_slice_count も増やす必要があります。そうしないと、HTTP 400 エラーが返されます。 |
max_query_slice_count | いいえ | 1 回のクエリで許可される候補スライスの最大数です。リクエストレベルの query_slice_count はこの制限を超えることはできません。デフォルト値は 512 です。有効値は 1 から 10000 です。この値は default_query_slice_count より小さくすることはできません。 |
slice_strategy の値が exact である名前空間モードで空でない config を渡すと、HTTP 400 エラーが返されます。
vector_dims は重心の次元を指定しますが、mappings は dense_vector.dims を使用してドキュメントベクトルの次元を指定します。スライスの自動選択中、default_query_vector_path で指定されたクエリベクトルは、重心と同じ次元を持つ必要があります。この例では、スライスの選択とドキュメントの取得に同じ knn.query_vector を使用するため、両方の次元が 2 に設定され、同じベクトルモデルが使用されます。vector_dims だけを変更しても、既存のベクトルの次元が自動的に削減されることはありません。
settings、mappings、容量パラメーターなどの残りの作成パラメーターは、名前空間モードのものと同じです。詳細については、「コレクション管理リファレンス」をご参照ください。デフォルト値における以下の 2 つの違いに注意してください:
| パラメーター | 名前空間モードでのデフォルト値 | ベクトルクラスターリコールモードでのデフォルト値 |
auto_create_slice | true | false |
index.sliced_postings.enabled | true | false |
auto_create_slice はデフォルトで無効になっています。これは、ベクトルクラスターがスライスの自動選択に参加するには、重心を登録する必要があるためです。書き込み中に自動作成すると、重心のないスライスが生成され、そのデータは自動的にリコールされることはありません。ビジネスでこの動作が許容できない限り、auto_create_slice=false を維持し、最初に重心を登録してからデータを書き込んでください。
バッキングの事前作成 (任意、推奨)
バッキングはデフォルトでオンデマンドで作成されます。一括インポートの前に、5 つの基盤となるインデックスを事前作成することで、新しいベクトルクラスターのデータがそれらに分散され、最初の書き込み時のインデックス作成の待機時間が短縮されます。本番環境では、ベクトルクラスターの増加、データ量、シャードリソースに基づいて数を調整してください。
PUT /_slice_collection/products/backings?count=5acknowledged=true であること、および backings に 5 つのインデックスが含まれていることを確認します。事前作成では、既存のスライスは移行されず、重心も生成されません。バッキングを追加するセマンティクスと割り当てポリシーの変更については、「バッキングの事前作成」をご参照ください。
スライス重心の登録
スライスの自動選択に参加するすべてのスライスには、重心が必要です。このステップはスキップできません。重心の取得は、常に cosine 類似度と bbq_disk インデックスを使用した近似最近傍 (ANN) 検索を実行します。これは、ドキュメントベクトルフィールドの similarity 設定によって変更されることはありません。
単一のスライス重心の登録
次のリクエストは、スライス cluster-a の重心を登録します:
PUT /_slice_collection/products/slices/cluster-a
{
"vector": [0.9, 0.1]
}HTTP 応答が成功しても、重心が作成されたことは保証されません。「登録結果の確認 (単一およびバッチ)」で説明されているように、トップレベルの errors フィールドと、items 内のすべての要素の result を確認してください。
スライス重心のバッチ登録
オフラインのクラスタリングジョブは通常、複数のベクトルクラスターの重心を同時に生成します。バッチ API を使用して、1 つのリクエストでそれらを登録できます:
PUT /_slice_collection/products/slices
{
"slices": [
{ "slice": "cluster-b", "vector": [0.1, 0.9] },
{ "slice": "cluster-c", "vector": [0.6, 0.4] }
]
}各アイテムのスライス名は slice または slice_id で指定できますが、同じアイテム内ではどちらか一方しか使用できません。1 回のリクエストで最大 20,480 個のスライスを登録でき、スライス名はリクエスト内で一意である必要があります。
登録結果の確認 (単一およびバッチ)
単一登録 API とバッチ登録 API の両方で、HTTP 200 応答においてアイテムレベルのエラーを報告できます。これには、重心の次元と config.vector_dims の不一致などが含まれます。HTTP リクエストが成功したからといって、すべてのベクトルクラスターが正常に登録されたわけではありません。2xx 以外の応答を処理することに加えて、トップレベルの errors フィールドと、items 内のすべての要素の result を確認する必要があります:created は重心が作成されたこと、updated は重心が更新されたこと、noop は内容が変更されなかったこと、failed は失敗したことを示します。失敗したアイテムには文字列型の error フィールドが含まれ、成功したアイテムに含まれる backing_index フィールドは含まれません。
{
"acknowledged": true,
"errors": false,
"items": [
{
"slice_id": "cluster-b",
"result": "created",
"backing_index": ".sc-products-...-00000"
},
{
"slice_id": "cluster-c",
"result": "created",
"backing_index": ".sc-products-...-00001"
}
]
}各重心の次元は config.vector_dims と一致する必要があります。重心のないスライスは明示的にアクセスできますが、候補スライスの自動選択には参加しません。同じ名前のスライスを再度登録すると、重心が変更された場合は updated が返され、変更されていない場合は noop が返されます。どちらの場合も、すでに書き込まれているドキュメントは移動されません。
ベクトルデータの書き込み
ドキュメントの書き込み方法は、コレクション作成時に routing_field を設定したかどうかによって異なります。routing_field が設定されている場合、システムは各ドキュメントのトップレベルフィールドからスライスを読み取ります。設定されていない場合、すべての書き込みリクエストまたは Bulk アイテムは、名前空間モードと同様に _slice を明示的に指定する必要があります。
通常の書き込みリクエストでは refresh を渡してはならず、アプリケーションコードは _refresh を呼び出してはなりません。 データが検索可能になるには、自動バックグラウンドリフレッシュを待つ必要があります。同期待機が許可される条件については、「リフレッシュとクエリの可視性」をご参照ください。
routing_field を使用したドキュメントの書き込み
routing_field を設定すると、システムはドキュメントのトップレベルフィールドからスライスを読み取るため、_slice を渡す必要はなくなります:
PUT /products/_doc/product-1
{
"cluster_id": "cluster-a",
"name": "example-product",
"embedding": [0.92, 0.08]
}明示的に _slice=cluster-a を指定することもできます。また、互換性のある API は routing=cluster-a も受け入れます。スライスを明示的に指定する場合、その値は routing_field (この例では cluster_id) で指定されたドキュメントフィールドの値と一致する必要があります。一致しない場合、HTTP 400 エラーが返されます。
ドキュメントの更新
routing_field を設定した後、スクリプトによる更新はサポートされません。一部のフィールドのみを変更するには、doc リクエストボディを持つ _update API を使用し、一致する _slice を明示的に指定します。古い値から新しい値を計算する必要がある場合は、アプリケーションで古い値を読み取り、新しい値を計算して書き戻します。他のリクエストによる更新を上書きしないように、同時実行制御には if_seq_no と if_primary_term を使用してください。
Copy または Branch 後のドキュメントの書き戻し
Copy 機能と Branch 機能はどちらも、ドキュメント内の routing_field の値を保持します。後でドキュメントを宛先スライスに書き戻す場合は、宛先を明示的に指定し、書き込まれるドキュメントのルーティングフィールドが宛先と一致することを確認してください。これにより、ドキュメントがソーススライスに書き戻されたり、検証エラーがトリガーされたりするのを防ぎます。詳細については、「データコピーのセマンティクス」をご参照ください。
routing_field を使用しないドキュメントの書き込み
routing_field が設定されていない場合、データの書き込みは名前空間モードと同じ方法で行われます。つまり、すべての書き込みリクエストまたは Bulk アイテムは _slice を明示的に指定する必要があります。Bulk、リフレッシュの可視性、_update_by_query、_delete_by_query などの他の書き込み動作については、「ドキュメントの書き込み、読み取り、クエリ操作」をご参照ください。
候補スライスの自動選択
クエリが設定されたパスにベクトルを提供すると、ベクトルクラスターリコールモードは検索対象の候補スライスを自動的に選択します。新しく書き込まれたデータは、自動バックグラウンドリフレッシュ後にのみ検索可能になります。書き込み後、約 5 秒待機し、結果に新しいデータが含まれていない場合は、もう 1 回の自動リフレッシュサイクルを待ってから再試行してください。
クエリの実行
クエリベクトルを使用して、候補スライスを自動的に選択します:
POST /products/_search?query_slice_count=2
{
"knn": {
"field": "embedding",
"query_vector": [0.91, 0.09],
"k": 10,
"num_candidates": 100
}
}timed_out=false と _shards.failed=0 であること、および hits.hits にこの例で書き込まれた product-1 が含まれていることを確認します。
次の表は、候補スライスの自動選択に関するパラメーターを説明しています:
| パラメーター | 説明 |
query_slice_count | このクエリで選択される候補スライスの数です。このパラメーターを省略するか 0 に設定すると、コレクションの default_query_slice_count が使用されます。 |
query_vector_path | コレクションのデフォルトのクエリベクトルパスを上書きします。有効値は knn.query_vector と knn.N.query_vector です。N は 0 から始まり、knn.query_vector は最初の KNN 句のクエリベクトルと同等です。 |
リクエストは、設定されたパスによって選択された 1 つのクエリベクトルのみを使用して、リクエスト全体の候補スライスを決定します。複数の KNN 句が個別にスライスを選択し、選択されたスライスセットの UNION を取ることはありません。他の KNN クエリやハイブリッドクエリ句も、この候補スライスのセットに制限されます。
query_slice_count が明示的にゼロ以外の値に設定されている場合、その値は 1 から max_query_slice_count の範囲内である必要があります。そうでない場合、HTTP 400 エラーが返されます。
リクエストが _slice または互換性のある routing パラメーターを明示的に指定する場合、クエリは指定された範囲内で実行されます。これらのスライスが重心を登録しているかどうかは関係ありません。重心の要件は、候補スライスの自動選択にのみ適用されます。つまり、登録された重心を持つスライスのみが考慮されます。
クラスター設定 apack.slice_collection.search.default_to_all_slices が無効 (デフォルト) の場合、設定されたパスにクエリベクトルがないと HTTP 400 エラーが返されます。この場合、_slice を明示的に指定してください。この設定を有効にすると、クエリベクトルが見つからない場合はすべてのスライスをクエリするフォールバック動作になります。通常の運用クエリでは、この設定を無効のままにし、全スライスフォールバックに依存しないでください。無効なパス、クエリベクトルの提供に query_vector_builder を使用した場合、またはクエリベクトルの次元が vector_dims と一致しない場合は、依然として HTTP 400 エラーが返され、この設定ではこれらのエラーをバイパスできません。この設定の詳細については、「クエリ範囲の指定」をご参照ください。
Count API (_count) のリクエストボディには、スライスの自動選択に必要なインラインクエリベクトルが含まれていないため、スライスを自動的に選択できません。全スライスフォールバックがデフォルトで無効になっている間は、_slice を明示的に指定する必要があります。クエリベクトルを含まない他のクエリも、範囲を明示的に指定する必要があります。
既知の候補スライスのプレウォーム (任意)
どのクラスターにアクセスされるかを予測できる場合は、事前にプレウォームすることで、コールドデータに対する最初のクエリのレイテンシーを短縮できます。この例では、cluster-a には 1 つのドキュメントしか書き込まれていないため、一度プレウォームできます:
POST /products/_warm_slice?_slice=cluster-a&wait_for_completion=true&timeout=60sリクエストが成功し、_shards.failed=0 であることを確認します。_shards.total=0 の場合は、まずクエリシャードが利用可能であることを確認し、実際のクエリを使用してデータが検索可能であることを確認してから、必要に応じてプレウォームを再試行してください。この例ではデータはすでに書き込まれています。同期待機は、この例を検証するためにのみ使用されます。本番環境では、予測可能なアクセス範囲を事前に非同期でプレウォームし、同時実行数を制御してください。クラスターの自動選択クエリの前に、すべてのクラスターを反復処理してプレウォームしないでください。詳細については、「スライスキャッシュのウォームアップ」をご参照ください。
一般的な HTTP 400 エラー
リクエストが HTTP 400 エラーを返す場合は、リクエストを以下の一般的な原因と比較してください:
| 原因 | セクション |
default_query_slice_count が max_query_slice_count より大きい値に設定され、同じリクエストで max_query_slice_count が増加されていない。 | コレクションの作成 |
名前空間モード (exact) で空でない config が渡された。 | コレクションの作成 |
routing_field で指定されたドキュメントフィールドの値と、明示的に指定された _slice または routing の値が一致しない。 | ベクトルデータの書き込み |
query_slice_count が、1 から max_query_slice_count の範囲外のゼロ以外の値に明示的に設定された。 | 候補スライスの自動選択 |
apack.slice_collection.search.default_to_all_slices が無効な状態で、設定されたパスにクエリベクトルがない。 | 候補スライスの自動選択 |
クエリベクトルのパスが無効である、クエリベクトルの提供に query_vector_builder が使用されている、またはクエリベクトルの次元が vector_dims と一致しない。これらのエラーは、apack.slice_collection.search.default_to_all_slices が有効な場合でも返されます。 | 候補スライスの自動選択 |
スライス内でのベクトル取得
query_slice_count は候補スライスの数を制御しますが、ドキュメントベクトルフィールドのインデックスタイプ、visit_percentage、および num_candidates は、選択された範囲内での KNN を制御します。フィールドとクエリパラメーターについては、「ベクトルフィールドと KNN」をご参照ください。2 つの機能の責任分担とそれらの選択方法については、「DiskBBQ との関係」をご参照ください。