使用 StructArray 進行篩選搜尋
請使用此頁面,為 StructArray 欄位的向量搜尋新增標量篩選功能。StructArray 篩選分為兩個層級:列層級篩選用於選取父實體,而元素層級篩選則用於限制哪些 Struct 元素會參與元素層級的向量搜尋。
本頁面使用來自「建立 StructArray 欄位」中的tech_articles 集合。該集合包含一個名為chunks 的 StructArray 欄位,其中包含諸如section 、page 、quality_score 及has_code 等標量子欄位,以及用於搜尋的向量子欄位。
選擇篩選類型
| 目標 | 用途 | 結果行為 |
|---|---|---|
根據頂層標量欄位進行篩選,例如category 。 | 常規篩選表達式。 | 在搜尋之前或期間選取父實體。 |
| 將元素層級向量搜尋限制為符合標量條件的 Struct 元素。 | element_filter. | 僅搜尋符合條件的 Struct 元素,並可回傳匹配元素的偏移量。 |
| 根據是否有任何、所有或特定數量的 Struct 元素符合謂詞來選取實體。 | MATCH_ANY、MATCH_ALL 、MATCH_LEAST 、MATCH_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" 的實體。它不會識別出單一符合條件的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 ,且不得將element_filter 或MATCH_* 嵌套於另一個 StructArray 運算子之中。
使用 MATCH 運算子篩選實體
當篩選條件需根據父實體的 Struct 元素來判定其是否符合資格時,請使用MATCH_* 運算子。這些運算子屬於列級篩選:它們會選取實體,但本身不會回傳元素偏移量。
| 運算子 | 適用於 | 範例 |
|---|---|---|
MATCH_ANY | 至少有一個 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_MOST | 最多有N 個 Struct 元素必須滿足該謂詞。 | MATCH_MOST(chunks, $[section] == "appendix", threshold=1) |
MATCH_EXACT | 必須有恰好N 個 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]",
],
)
此處使用MATCH_ANY ,是因為 EmbeddingList 的搜尋結果屬於實體層級。此篩選條件要求該實體中至少有一個片段為高品質的"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_req 上的expr 則僅會限制 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 判別式、幾何函式、Timestamptz 表達式以及泛型函式呼叫),請參閱StructArray 運算子。
常見錯誤
在 `
element_filter` 或 `MATCH_*` 之外使用 `$[subfield]`。使用 `
chunks.section` 代替 `element_filter(chunks, $[section] == "index")` 等 `StructArray` 運算子語法。僅需進行列級篩選時卻使用 `
element_filter`。若僅需選取實體,請改用 `MATCH_ANY`。預期 `
MATCH_*` 會返回元素偏移量。這些運算子僅用於選取實體,本身並不會識別出單一符合條件的元素。撰寫如
$[has_code]這類未加修飾的布林謂詞。請改用如$[has_code] == true這類明確的比較運算子。將 `
element_filter` 置於同一篩選表達式中頂層判別式的前方。
下一步
若要檢視完整的 StructArray 篩選語法,請參閱《StructArray 運算子》。
若要先執行未過濾的向量搜尋,請參閱《使用 StructArray 進行基本向量搜尋》。
若要為常用 StructArray 篩選條件建立標量索引,請參閱《索引 StructArray 欄位》。
若要查看特定版本的篩選與搜尋限制,請參閱《StructArray 限制》。