StructArray を使用したフィルタリング検索

このページでは、StructArrayフィールドに対するベクトル検索にスカラーフィルタリングを追加します。StructArrayのフィルタリングには2つのレベルがあります。行レベルのフィルタは親エンティティを選択し、要素レベルのフィルタは、要素レベルのベクトル検索に参加するStruct要素を制限します。

このページでは、「StructArrayフィールドの作成」にあるtech_articles コレクションを使用しています。このコレクションには、chunks という名前のStructArrayフィールドがあり、sectionpagequality_scorehas_code などのスカラーサブフィールドに加え、検索用のベクトルサブフィールドが含まれています。

フィルタの種類を選択してください

目標使用結果の挙動
category などのトップレベルのスカラーフィールドでフィルタリングします。通常のフィルタ式。検索の前または検索中に親エンティティを選択します。
要素レベルのベクトル検索を、スカラー条件に一致する Struct 要素に制限します。element_filter一致する Struct 要素のみを検索し、一致した要素のオフセットを返すことができます。
Struct 要素のいずれか、すべて、または特定の数が述語に一致するかどうかに基づいてエンティティを選択します。MATCH_ANYMATCH_ALLMATCH_LEASTMATCH_MOST 、またはMATCH_EXACT行レベルのフィルタリング。これらの演算子自体はオフセットを返しません。

このページでは、検索ワークフローにおける StructArray フィルターの使用方法について説明します。完全な構文規則、サポートされている述語タイプ、およびサポートされていない述語マトリックスについては、「StructArray 演算子」を参照してください。

トップレベルフィールドによるフィルタリング

条件が個々の Struct 要素ではなく親エンティティに属する場合は、通常のフィルタ式を使用します。これは、EmbeddingList 検索と要素レベル検索の両方で機能します。

from pymilvus import MilvusClient
from pymilvus.client.embedding_list import EmbeddingList

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

query = EmbeddingList()
query.add([0.12, 0.21, 0.32, 0.44])
query.add([0.18, 0.23, 0.29, 0.36])

results = client.search(
    collection_name="tech_articles",
    data=[query],
    anns_field="chunks[emb_list_vector]",
    filter='category == "search"',
    limit=3,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
    ],
)

上記のフィルタは、トップレベルのcategory フィールドが"search" であるエンティティのみを選択します。これは、1つの一致するStruct要素を特定するものではありません。

スカラー条件を、要素レベルのベクトル検索に参加する同じStruct要素に適用する必要がある場合は、element_filter(structArrayField, predicate) を使用します。述語内では、$[subfield] を使用して、現在のStruct要素のスカラーサブフィールドを参照します。

query_vector = [0.19, 0.24, 0.30, 0.37]

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

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

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

この例では、最上位の述語 `category == "search" ` が候補エンティティを選択し、`element_filter ` が、`section`、`quality_score`、および `has_code ` のすべてが同じ Struct 要素内で一致するチャンクに、要素レベルのベクトル検索を制限します。

警告

トップレベルの述語をelement_filter と組み合わせる場合は、element_filter を式の最後に配置してください。フィルタ式にはelement_filter を1つしか含めることができず、element_filterMATCH_* を別のStructArray演算子の内部にネストすることはできません。

MATCH演算子を使用したエンティティのフィルタリング

フィルタが、親エンティティの Struct 要素に基づいてそのエンティティが条件を満たすかどうかを判断する必要がある場合は、MATCH_* 演算子を使用します。これらの演算子は行レベルのフィルタであり、エンティティを選択しますが、それ自体では要素のオフセットを返しません。

演算子次のような場合に使用します
MATCH_ANY少なくとも1つのStruct要素が述語を満たす必要があります。MATCH_ANY(chunks, $[section] == "index")
MATCH_ALLすべての Struct 要素が述語を満たす必要があります。MATCH_ALL(chunks, $[quality_score] > 0.5)
MATCH_LEAST少なくともN 個のStruct要素が述語を満たす必要があります。MATCH_LEAST(chunks, $[has_code] == true, threshold=2)
MATCH_MOSTN 個以下のStruct要素が述語を満たす必要があります。MATCH_MOST(chunks, $[section] == "appendix", threshold=1)
MATCH_EXACTN 個のStruct要素が、その述語を満たさなければなりません。MATCH_EXACT(chunks, $[section] == "summary", threshold=1)
filter_expr = (
    'category == "search" && '
    'MATCH_ANY(chunks, $[section] == "index" && $[quality_score] > 0.9)'
)

results = client.search(
    collection_name="tech_articles",
    data=[query],
    anns_field="chunks[emb_list_vector]",
    filter=filter_expr,
    limit=3,
    output_fields=[
        "doc_id",
        "title",
        "category",
        "chunks[text]",
        "chunks[section]",
        "chunks[quality_score]",
    ],
)

EmbeddingList の検索結果はエンティティレベルであるため、ここでは `MATCH_ANY ` を使用します。このフィルターでは、エンティティ内の少なくとも 1 つのチャンクが、高品質な `"index" ` チャンクである必要がありますが、検索結果自体は依然として親エンティティを表しています。

ハイブリッド検索では、条件を適用すべき箇所に StructArray フィルタを適用します。トップレベルのフィルタは、ハイブリッド検索全体で共有できます。element_filter は、要素レベルの制約を必要とする StructArray 要素レベルのリクエストに添付する必要があります。

from pymilvus import AnnSearchRequest, RRFRanker

query_vector = [0.19, 0.24, 0.30, 0.37]

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

chunk_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="chunks[emb]",
    limit=10,
    expr='element_filter(chunks, $[section] == "index" && $[quality_score] > 0.9)',
)

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

filter 引数はトップレベルのエンティティ条件を適用しますが、chunk_reqexpr は、StructArrayの要素レベルのベクトルリクエストのみを制限します。サポートされているハイブリッド検索の組み合わせおよびバージョン固有の制限については、「StructArrayを使用したハイブリッド検索」および「StructArrayの制限」を参照してください。

述語のサポート概要

StructArray 述語ではスカラーサブフィールドを使用してください。ベクトルサブフィールドは、スカラー述語の入力には使用できません。

サブフィールドの型代表的な述語の例
BOOL$[has_code] == true,!($[has_code] == true)
整数型$[page] >= 2,$[page] in [1, 2, 3]
FLOAT,DOUBLE$[quality_score] > 0.9,0.7 < $[quality_score] < 0.95
VARCHAR$[section] == "index",$[text] like "range%"
ベクトルサブフィールド$[...] のスカラー述語の入力としてはサポートされていません。代わりに、ベクトル検索を通じてベクトルサブフィールドを使用してください。

JSONパス、配列コンテナ関数、テキスト一致関数、$[...] に対する null 述語、Geometry 関数、Timestamptz 式、およびジェネリック関数の呼び出しなど、サポートされていないケースについては、「StructArray 演算子」を参照してください。

よくある間違い

  • element_filterMATCH_* の外で$[subfield] を使用すること。

  • element_filter(chunks, $[section] == "index") などの StructArray 演算子構文の代わりにchunks.section を使用すること。

  • 行レベルのフィルタリングのみが必要な場合に `element_filter ` を使用すること。エンティティを選択するだけなら、代わりに `MATCH_ANY ` を使用してください。

  • MATCH_* が要素のオフセットを返すことを期待しないこと。これらの演算子はエンティティを選択するものであり、それ自体では一致した要素を特定するものではありません。

  • $[has_code] のような単純なブール述語を記述すること。$[has_code] == true のような明示的な比較を使用してください。

  • 同じフィルタ式内で、element_filter をトップレベルの述語の前に配置すること。

次の手順

  1. StructArray フィルタの構文全体を確認するには、「StructArray 演算子」を参照してください。

  2. まず、フィルタリングを行わないベクトル検索を実行するには、「StructArray を使用した基本的なベクトル検索」を参照してください。

  3. 頻繁に使用する StructArray フィルタ用のスカラーインデックスを作成するには、「StructArray フィールドのインデックス作成」を参照してください。

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