StructArray を使用した範囲検索

このページでは、StructArrayのベクトルサブフィールドに対して範囲検索を実行できます。範囲検索では、スコアまたは距離が指定された範囲内に収まるベクトルヒットが返されます。StructArrayフィールドの場合、要素レベルのベクトル検索と組み合わせて範囲検索を使用します。この場合、各Struct要素が個別に検索されます。

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

StructArray に対する範囲検索の適用方法

検索モード範囲検索の動作結果の粒度
EmbeddingList 検索サポートされていません。該当なし。
要素レベルの検索radius および、必要に応じてrange_filter を使用した通常のベクトルクエリを使用してください。構造体要素レベル。
ハイブリッド検索StructArray リクエストが要素レベルのベクトルフィールドを対象としている場合にサポートされます。EmbeddingList レベルのリクエストでは、範囲検索はサポートされていません。要素レベルのサブ検索、その後ハイブリッド再ランク付け。

最も近い Struct 要素のみが必要な場合は、StructArray を使用した基本ベクトル検索から始めてください。結果がトップ K ランキングだけでなく、スコアや距離の境界条件も満たす必要がある場合は、範囲検索を使用してください。

開始する前に

範囲検索を実行する前に、コレクション、データ、およびインデックスを準備してください。

要件詳細
StructArray フィールドコレクションには、chunks などの StructArray フィールドが含まれています。
要素レベルのベクトルサブフィールド対象のベクトルサブフィールドはchunks[emb] であり、chunks[emb_list_vector] ではありません。
インデックス測定基準このベクトルサブフィールドは、COSINEIP 、またはL2 などの通常のベクトルメトリックでインデックス付けされています。
クエリデータクエリは、EmbeddingList ではなく、通常のベクトルです。

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

radius および range_filter の使用

radius を設定して、検索範囲を定義します。内部境界も必要な場合は、range_filter を設定します。方向は、距離が短いほど良いか、類似度スコアが高いほど良いかによって異なります。

メトリックタイプスコアが高いほど良い?range_filter を使用する場合の範囲条件
L2いいえ。距離が小さいほど良い。range_filter <= distance < radius
IP,COSINEはい。スコアが大きいほど良い。radius < distance <= range_filter

radius のみが設定されている場合、範囲検索では、メトリックの外側境界を満たすヒットが返されます。埋め込みのスコアまたは距離のスケールに応じて値を選択してください。

次の例では、chunks[emb] ベクトルがクエリベクトルと十分に類似している個々のチャンクを検索します。各検索結果は、一致したStruct要素を表します。

from pymilvus import MilvusClient

client = MilvusClient(
    uri="http://localhost:19530",
    token="root:Milvus",
)

query_vector = [0.19, 0.24, 0.30, 0.37]

results = client.search(
    collection_name="tech_articles",
    data=[query_vector],
    anns_field="chunks[emb]",
    search_params={
        "params": {
            "radius": 0.80,
            "range_filter": 0.95,
        },
    },
    limit=10,
    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["id"],
            "distance:", hit["distance"],
            "offset:", hit.get("offset"),
            "entity:", hit["entity"],
        )

この例では、COSINE は類似度型のメトリックであるため、結果の範囲はradius より大きく、range_filter 以下となります。返されるoffset の値は、chunks 配列内の一致したStruct要素を識別します。

スカラーフィルタの追加

要素レベルの範囲検索と StructArray のスカラーフィルタリングを組み合わせることができます。親エンティティのフィールドにはトップレベルの述語を使用し、element_filter を使用して、ベクトル範囲検索の対象となる Struct 要素を制限します。

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]",
    search_params={
        "params": {
            "radius": 0.80,
            "range_filter": 0.95,
        },
    },
    filter=filter_expr,
    limit=10,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
        "chunks[quality_score]",
    ],
)

トップレベルの述語は候補エンティティを選択します。element_filter 述語は、ベクトル範囲検索を一致するStruct要素に限定します。フィルタリングのその他の例については、「StructArrayを使用したフィルタリング検索」を参照してください。

StructArrayの要素レベルのベクトルフィールドは、ハイブリッド検索における範囲検索をサポートしています。StructArrayの要素レベルのベクトルフィールドを対象とするAnnSearchRequest に、radius を追加し、必要に応じてrange_filter も追加します。

from pymilvus import AnnSearchRequest, RRFRanker

title_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="title_vector",
    limit=10,
)

chunk_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="chunks[emb]",
    param={
        "params": {
            "radius": 0.80,
            "range_filter": 0.95,
        },
    },
    limit=10,
    expr='element_filter(chunks, $[section] == "index")',
)

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

この例では、chunks[emb] サブリクエストのみが範囲検索パラメータを使用します。StructArray リクエストは依然として要素レベルのセマンティクスに従います。つまり、範囲の境界は、ハイブリッド検索が結果を結合して再ランク付けを行う前に、Struct 要素のヒットに適用されます。

範囲検索結果の解釈

結果項目意味
id一致した Struct 要素を含むエンティティのプライマリキー。
distance またはスコアクエリベクトルと一致したStruct要素のベクトルとの間のスコアまたは距離。
offset返される際の、StructArrayフィールド内における一致したStruct要素の0を基点とする位置。
重複する主キーあり得ます。同じエンティティ内の複数の Struct 要素が、指定された範囲に含まれる場合があります。
limitこれは要素のヒットに適用され、一意の親エンティティには適用されません。

制限事項

  • StructArray ベクトルサブフィールドの範囲検索には、EmbeddingList クエリやMAX_SIM* メトリックを使用しないでください。EmbeddingList レベルの検索では、範囲検索はサポートされていません。

  • 範囲検索とグループ化検索を組み合わせて使用しないでください。親エンティティごとに 1 つの結果が必要な場合は、範囲パラメータを指定せずに要素レベルの検索を実行し、サポートされている場合はグループ化を使用してください。

  • StructArrayの要素レベルのベクトルフィールドでは、ハイブリッド範囲検索がサポートされています。EmbeddingListレベルのStructArrayリクエストではサポートされていません。

よくある間違い

  • chunks[emb_list_vector] に対して範囲検索を実行すること。これは EmbeddingList 検索を目的としたものです。

  • 要素レベルの範囲検索において、COSINE などの通常のメトリックの代わりにMAX_SIM_COSINE を使用すること。

  • 通常のベクトルクエリの代わりに、EmbeddingList クエリを使用すること。

  • 範囲検索の結果が親エンティティごとに一意であると想定している。範囲検索では、一致する Struct 要素のヒットが返されます。

  • 必須のサブフィールドパス構文 `chunks[emb]` の代わりに `chunks.emb ` を使用している。

次のステップ

  1. StructArray の 2 つの基本的なベクトル検索モードについて学ぶには、「StructArray を使用した基本的なベクトル検索」を参照してください。

  2. 範囲検索にスカラーフィルターを追加するには、「StructArray を使用したフィルター検索」を参照してください。

  3. サポートされている場合、親エンティティごとに最大 1 件の結果を返すには、「StructArray を使用したグループ化検索」を参照してください。

  4. バージョンごとの検索制限を確認するには、「StructArray の制限」を参照してください。