使用 StructArray 進行分組搜尋

請使用此頁面,根據父實體對 StructArray 的元素層級搜尋結果進行分組。當多個 Struct 元素符合查詢條件時,元素層級搜尋可能會從同一實體中返回多個搜尋結果。分組功能會將這些元素搜尋結果合併,使每個父實體最多只出現一次。

本頁面使用《建立 StructArray 欄位》中的tech_articles 集合。該集合包含一個名為chunks 的 StructArray 欄位。其中chunks[emb] 向量子欄位已針對元素層級搜尋進行索引,並採用標準向量度量標準。

分組機制如何套用至 StructArray

搜尋模式分組行為結果行為
EmbeddingList 搜尋不支援。不適用。
元素層級搜尋透過主鍵分組可支援此功能。每個父實體最多返回一個結果。元素層級的元資料會被保留,因此當 API 或 SDK 公開時,可返回所選元素的索引或偏移量。
混合搜尋僅在所有子搜尋皆針對同一 StructArray 欄位下的元素層級向量欄位時才受支援。在處理最終結果之前,元素層級的子搜尋會依據主鍵進行分組。

當未分組的元素層級搜尋會返回過多重複的父實體時,請使用分組功能。若您希望將每個符合條件的 Struct 元素視為獨立的搜尋結果,請使用不帶 `group_by_field`的 StructArray 基本向量搜尋

開始之前

在執行分組搜尋之前,請先準備好集合、資料和索引。

需求詳細資訊
元素層級向量子欄位請使用 StructArray 向量子欄位(例如chunks[emb] ),並以常規向量度量作為索引。
常規向量查詢請使用一般查詢向量,而非EmbeddingList
主鍵分組請將集合主鍵設定為 `group_by_field`,例如 `doc_id`。
不使用範圍參數請勿將分組搜尋與範圍搜尋參數(例如radiusrange_filter )結合使用。

有關索引設定,請參閱「Index StructArray 欄位」。

以下範例會先搜尋個別區塊,然後根據父實體的主鍵將元素搜尋結果進行分組。

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]",
    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["id"],
            "distance:", hit["distance"],
            "offset:", hit.get("offset"),
            "entity:", hit["entity"],
        )

若未進行分組,當多個區塊符合查詢條件時,相同的 `doc_id ` 可能會出現多次。使用 `group_by_field="doc_id"` 時,每個父實體最多只會出現一次。分組可保留元素層級的元資料,因此當 API 或 SDK 公開相關資訊時,分組後的結果仍可包含所選的 Struct 元素索引或偏移量。

新增標量篩選條件

您可以將分組搜尋與 StructArray 標量篩選結合使用。當標量條件需限制哪些 Struct 元素參與元素層級向量搜尋時,請使用 `element_filter `。

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] ,且兩者均使用標準向量度量進行索引。

from pymilvus import AnnSearchRequest, RRFRanker

index_chunk_req = AnnSearchRequest(
    data=[query_vector],
    anns_field="chunks[emb]",
    limit=10,
    expr='element_filter(chunks, $[section] == "index")',
)

code_chunk_req = AnnSearchRequest(
    data=[code_query_vector],
    anns_field="chunks[code_emb]",
    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]",
    ],
)

在此範例中,兩個子請求皆針對同一 StructArray 欄位(chunks )下的元素層級向量子欄位。若混合了一般向量欄位、不同的 StructArray 欄位或 EmbeddingList 層級的請求,混合搜尋將不支援元素層級的分組操作。

解析分組結果

結果項目含義
id分組父實體的主鍵。
distance 或分數該父實體所選 Struct 元素的分數或距離。
offset選取之 Struct 元素在回傳時的零起始位置。
重複的主鍵按主鍵分組時不應出現此情況。
limit適用於已分組的父實體結果。

限制

  • 分組搜尋僅適用於元素層級的 StructArray 向量搜尋。EmbeddingList 搜尋和 EmbeddingList 層級的混合搜尋不支援「按...分組」。

  • 請將主鍵用作 `group_by_field`。StructArray 元素層級的分組並非針對任意標量欄位的通用分組功能。

  • 請勿將分組搜尋與範圍搜尋結合使用。

  • 請勿在分組搜尋中使用EmbeddingList 查詢或MAX_SIM* 指標。

  • 僅當所有子搜尋皆針對同一 StructArray 欄位下的元素層級向量欄位時,才支援混合分組。

  • 當混合搜尋同時包含一般向量場、不同的 StructArray 場或 EmbeddingList 層級請求時,則不支援混合分組。

常見錯誤

  • 將分組功能用於chunks[emb_list_vector] ,該功能原本是針對 EmbeddingList 搜尋設計的。

  • 根據非主鍵標量欄位進行分組。

  • 根據多個欄位進行分組。元素層級的 StructArray 分組僅支援主鍵分組。

  • 預期分組結果會代表每個匹配的 Struct 元素。分組功能每項父實體最多只會返回一個結果。

  • 假設分組後的元素層級搜尋會重新計算 EmbeddingList 風格的MAX_SIM* 分數。分組會彙總元素層級的搜尋結果;它並不會改變評分模型。

  • group_by_fieldradiusrange_filter 結合使用。

下一步

  1. 若要先了解未分組的元素層級搜尋,請閱讀《使用 StructArray 進行基本向量搜尋》。

  2. 若要為分組搜尋新增標量篩選條件,請參閱《使用 StructArray 進行篩選搜尋》。

  3. 若要使用分數或距離範圍取代分組,請參閱《使用 StructArray 進行範圍搜尋》。

  4. 若要查看 StructArray 的搜尋限制,請閱讀《StructArray 限制》