メインコンテンツまでスキップ

StructArray でのグループ化検索

このページを使用して、StructArray の要素レベルの検索結果を親エンティティでグループ化します。複数の Struct 要素がクエリに一致すると、要素レベルの検索で同じエンティティから複数のヒットが返されることがあります。グループ化はそれらの要素のヒットをまとめ、各親エンティティが最大 1 回だけ現れるようにします。

このページでは、StructArray フィールドの作成 の tech_articles コレクションを使用します。コレクションには chunks という名前の StructArray フィールドがあります。chunks[emb] ベクトルサブフィールドは、通常のベクトルメトリクスを使用した要素レベルの検索用にインデックスが作成されています。

例では、デフォルトのグループサイズである 1 を使用します。

これらの例を実行する前に、コレクションを作成し、サンプルデータを挿入し、必要なベクトルインデックスを作成して、コレクションをロードしてください。ここに示すフィールドには、4 次元のベクトルを使用します。各コードブロックは、そのコードブロック内で改めて定義されていない限り、同じ言語の前の例で定義された接続と変数を使用することを前提としています。

StructArray でのグループ化の適用方法​

検索モードグループ化の動作結果の動作
EmbeddingList 検索サポートされていません。該当しません。
要素レベルの検索プライマリキーによるグループ化でサポートされます。親エンティティごとに最大 1 件の結果を返します。要素レベルのメタデータは保持されるため、API または SDK で公開されている場合は、選択された要素のインデックスまたはオフセットを返すことができます。
ハイブリッド検索すべてのサブ検索が同じ StructArray フィールド配下の要素レベルのベクトルフィールドを対象とする場合にのみサポートされます。要素レベルのサブ検索は、最終的な結果処理の前にプライマリキーでグループ化されます。
📘Notes

グループ化されていない要素レベルの検索で重複する親エンティティが多数返される場合は、グループ化を使用してください。一致するすべての Struct 要素を個別のヒットとして取得する場合は、group_by_field を指定せずに StructArray での基本ベクトル検索 を使用してください。

事前準備​

グループ化検索を実行する前に、コレクション、データ、インデックスを準備します。

要件詳細
要素レベルのベクトルサブフィールドchunks[emb] のような StructArray のベクトルサブフィールドを使用し、通常のベクトルメトリクスでインデックスを作成します。
通常のベクトルクエリEmbeddingList ではなく、通常のクエリベクトルを使用します。
プライマリキーによるグループ化doc_id など、コレクションのプライマリキーを group_by_field として使用します。
範囲パラメーターの不使用グループ化検索を、radius や range_filter などの範囲検索パラメーターと組み合わせないでください。

インデックスの設定については、StructArray フィールドのインデックス作成 を参照してください。

次の例では、個々のチャンクを先に検索してから、要素のヒットを親エンティティのプライマリキーでグループ化します。

python
from pymilvus import MilvusClient

client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN",
)

query_vector = [0.19, 0.24, 0.30, 0.37]

results = client.search(
collection_name="tech_articles",
data=[query_vector],
anns_field="chunks[emb]",
limit=5,
group_by_field="doc_id",
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
"chunks[page]",
"chunks[quality_score]",
],
)

for hits in results:
for hit in hits:
print(
"doc_id:", hit["doc_id"],
"distance:", hit["distance"],
"offset:", hit.get("offset"),
"entity:", hit["entity"],
)

グループ化しない場合、複数のチャンクがクエリに一致すると、同じ doc_id が複数回現れることがあります。group_by_field="doc_id" を指定すると、各親エンティティは最大 1 回だけ現れます。グループ化は要素レベルのメタデータを保持するため、API または SDK で公開されている場合は、グループ化された結果に選択された Struct 要素のインデックスまたはオフセットを含めることができます。

スカラーフィルターを追加する​

グループ化検索を StructArray のスカラーフィルタリングと組み合わせることができます。スカラー条件によって、要素レベルのベクトル検索に参加する Struct 要素を制限する場合は、element_filter を使用します。

python
query_vector = [0.19, 0.24, 0.30, 0.37]

filter_expr = (
'category == "search" && '
'element_filter(chunks, '
'$[section] == "index" && '
'$[quality_score] > 0.9)'
)

results = client.search(
collection_name="tech_articles",
data=[query_vector],
anns_field="chunks[emb]",
filter=filter_expr,
limit=5,
group_by_field="doc_id",
output_fields=[
"doc_id",
"title",
"category",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)

最上位の述語は候補エンティティを選択します。element_filter 述語は、要素レベルのベクトル検索を一致する Struct 要素に制限します。その後、グループ化によって一致する要素のヒットがプライマリキーでまとめられます。

StructArray でのハイブリッドグループ化は要素レベルの機能です。すべてのサブ検索が同じ StructArray フィールド配下の要素レベルのベクトルフィールドを対象とする場合にのみサポートされます。グループ化された StructArray ハイブリッド検索では、EmbeddingList レベルのリクエストを使用しないでください。

次の例では、chunks StructArray フィールドに chunks[emb] と chunks[code_emb] という 2 つの要素レベルのベクトルサブフィールドがあり、どちらも COSINE でインデックスが作成されていることを前提としています。コレクションの作成時に、追加の 4 次元 code_emb サブフィールドを定義してデータを格納してください。これは、上記でリンクされている基本スキーマには含まれていません。

python
from pymilvus import AnnSearchRequest, RRFRanker

query_vector = [0.19, 0.24, 0.30, 0.37]
code_query_vector = [0.18, 0.23, 0.29, 0.36]

index_chunk_req = AnnSearchRequest(
data=[query_vector],
anns_field="chunks[emb]",
param={"metric_type": "COSINE"},
limit=10,
expr='element_filter(chunks, $[section] == "index")',
)

code_chunk_req = AnnSearchRequest(
data=[code_query_vector],
anns_field="chunks[code_emb]",
param={"metric_type": "COSINE"},
limit=10,
expr='element_filter(chunks, $[has_code] == true)',
)

results = client.hybrid_search(
collection_name="tech_articles",
reqs=[index_chunk_req, code_chunk_req],
ranker=RRFRanker(),
limit=5,
group_by_field="doc_id",
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
],
)

Milvus 3.0.2 に付属する Go クライアントのソースでは、NewHybridSearchOption を通じて最終的なハイブリッドグループ化を公開していません。各サブリクエストに WithGroupByField を設定しても、最終的なハイブリッドグループ化は構成されません。NodeJS 3.0.6 も、ハイブリッドランキングパラメーターからトップレベルの group_by_field を省略しています。この例では、上記に示す API のいずれかを使用してください。

この例では、両方のサブリクエストが同じ StructArray フィールド chunks 配下の要素レベルのベクトルフィールドを対象としています。ハイブリッド検索で通常のベクトルフィールド、異なる StructArray フィールド、または EmbeddingList レベルのリクエストを混在させる場合、要素レベルの group-by はサポートされません。

グループ化された結果を解釈する​

結果項目意味
プライマリキー(これらの例では doc_id)グループ化された親エンティティのプライマリキーです。
distance またはスコアその親エンティティに対して選択された Struct 要素のスコアまたは距離です。
offset返される場合の、選択された Struct 要素の 0 から始まる位置です。
プライマリキーの重複プライマリキーでグループ化する場合、想定されません。
limitグループ化された親エンティティの結果に適用されます。

制限事項​

  • グループ化検索は、要素レベルの StructArray ベクトル検索にのみ適用されます。EmbeddingList 検索および EmbeddingList レベルのハイブリッド検索では、group-by はサポートされません。

  • プライマリキーを group_by_field として使用してください。StructArray の要素レベルのグループ化は、任意のスカラーフィールドに対する汎用的な group-by ではありません。

  • グループ化検索を範囲検索と組み合わせないでください。

  • グループ化検索には、EmbeddingList クエリまたは MAX_SIM* メトリクスを使用しないでください。

  • ハイブリッドグループ化は、すべてのサブ検索が同じ StructArray フィールド配下の要素レベルのベクトルフィールドを対象とする場合にのみサポートされます。

  • ハイブリッド検索で通常のベクトルフィールド、異なる StructArray フィールド、または EmbeddingList レベルのリクエストを混在させる場合、ハイブリッドグループ化はサポートされません。

よくある間違い​

  • EmbeddingList 検索用の chunks[emb_list_vector] でグループ化を使用する。

  • プライマリキー以外のスカラーフィールドでグループ化する。

  • 複数のフィールドでグループ化する。StructArray の要素レベルのグループ化は、プライマリキーによるグループ化のみをサポートします。

  • グループ化された結果が、一致したすべての Struct 要素を表すと期待する。グループ化は、親エンティティごとに最大 1 件の結果を返します。

  • グループ化された要素レベルの検索が EmbeddingList 形式の MAX_SIM* スコアを再計算すると想定する。グループ化は要素レベルのヒットをまとめるだけで、スコアリングモデルは変更しません。

  • group_by_field を radius または range_filter と組み合わせる。

次のステップ​

  1. グループ化されていない要素レベルの検索を先に学ぶには、StructArray での基本ベクトル検索 を参照してください。

  2. グループ化検索にスカラーフィルターを追加するには、StructArray でのフィルター検索 を参照してください。

  3. グループ化の代わりにスコアまたは距離の境界を使用するには、StructArray での範囲検索 を参照してください。

  4. StructArray の検索制限を確認するには、StructArray の制限事項 を参照してください。