跳到主要内容
版本:v3.0.x

Range Search with StructArray

使用本页介绍的方法在 StructArray 向量子字段上执行 Range Search。Range Search 会返回分数或距离落在指定边界内的向量命中结果。对于 StructArray 字段,请结合元素级向量搜索使用 Range Search,其中每个 Struct 元素都会被独立搜索。

本页使用 Create a StructArray Field 中的 tech_articles Collection。该 Collection 包含一个名为 chunks 的 StructArray 字段。chunks[emb] 向量子字段已针对元素级搜索创建索引,并使用常规向量度量类型,例如 COSINEIPL2

How range search applies to StructArray

Search modeRange search 行为结果粒度
EmbeddingList search不支持。不适用。
Element-level search使用常规向量查询,并指定 radius,也可以选择指定 range_filterStruct 元素级别。
Hybrid search当 StructArray 请求以元素级向量字段为目标时支持。EmbeddingList 级别的请求不支持 Range Search。先执行元素级子搜索,然后进行 Hybrid reranking。

如果你只需要最近的 Struct 元素,请从 Basic Vector Search with StructArray 开始。若结果必须满足分数或距离边界,而不只是 top-K 排名,请使用 Range Search。

Before you begin

在运行 Range Search 之前,准备好 Collection、数据和 Index。

要求详情
StructArray fieldCollection 包含一个 StructArray field,例如 chunks
元素级 vector subfield目标 vector subfield 是 chunks[emb],而不是 chunks[emb_list_vector]
Index metricvector subfield 使用常规 vector metric 建立 Index,例如 COSINEIPL2
Query dataQuery data 是常规 vector,而不是 EmbeddingList

有关 Index 设置,请参阅 Index StructArray Fields

使用 radius 和 range_filter

设置 radius 来定义搜索边界。当你还需要内边界时,设置 range_filter。方向取决于较小的距离更优,还是较大的相似度分数更优。

Metric type分数越高越好吗?使用 range_filter 时的范围条件
L2否。距离越小越好。range_filter <= distance < radius
IP, COSINE是。分数越大越好。radius < distance <= range_filter

仅设置 radius 时,Range Search 会返回满足该 Metric 外边界的命中结果。请根据你的 Embedding 的分数或距离尺度选择取值。

以下示例会搜索单个 chunk,其 chunks[emb] 向量与查询向量足够相似。每个结果 hit 表示一个匹配的 Struct element。

Python
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 是相似度型 metric,因此结果范围为大于 radius 且小于等于 range_filter。返回结果中的 offset 值用于标识 chunks 数组中匹配的 Struct element。

Add scalar filters

你可以将元素级 range search 与 StructArray scalar filtering 结合使用。使用顶层 predicate 过滤父 Entity 字段,并使用 element_filter 限制哪些 Struct 元素参与 vector range search。

Python
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]",
],
)

顶层 predicate 用于选择候选 Entity。element_filter predicate 将 vector range search 限制在匹配的 Struct 元素中。更多过滤示例,请参见 Filtered Search with StructArray

StructArray 元素级向量字段支持在 Hybrid Search 中使用 Range Search。请在面向 StructArray 元素级向量字段的 AnnSearchRequest 中添加 radius,并可选添加 range_filter

Python
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] 子请求使用 range search 参数。StructArray 请求仍遵循元素级语义:在 Hybrid Search 合并并 rerank 结果之前,range 边界会先应用于命中的 Struct 元素。

Interpret range results

结果项含义
id包含匹配 Struct 元素的 Entity 的主键。
distance 或 score查询向量与匹配的 Struct 元素向量之间的分数或距离。
offset返回时,匹配的 Struct 元素在 StructArray 字段中的从零开始的位置。
重复的主键可能出现。同一 Entity 中的多个 Struct 元素可能落入指定范围内。
limit作用于元素级命中结果,而不是唯一的父 Entity。

Limitations

  • 不要对 StructArray vector 子字段的 range search 使用 EmbeddingList 查询或 MAX_SIM* metric。EmbeddingList 级别的 search 不支持 range search。

  • 不要将 range search 与 grouping search 组合使用。如果需要为每个父 Entity 返回一个结果,请执行不带 range 参数的元素级 search,并在支持的情况下使用 grouping。

  • StructArray 元素级 vector field 支持 Hybrid range search。不支持 EmbeddingList 级别的 StructArray 请求。

常见错误

  • chunks[emb_list_vector] 执行 Range Search,该字段用于 EmbeddingList search。

  • 在元素级 Range Search 中使用 MAX_SIM_COSINE,而不是 COSINE 等常规 metric。

  • 使用 EmbeddingList query,而不是常规 vector query。

  • 期望 Range Search 结果按父 Entity 去重。Range Search 返回匹配的 Struct 元素命中。

  • 使用 chunks.emb,而不是必需的子字段路径语法 chunks[emb]

后续步骤

  1. 要了解两种基本的 StructArray vector search 模式,请阅读 Basic Vector Search with StructArray

  2. 要为 range search 添加 scalar filter,请阅读 Filtered Search with StructArray

  3. 要在支持的情况下为每个父 Entity 最多返回一条结果,请阅读 Grouping Search with StructArray

  4. 要查看特定版本的 search 限制,请阅读 StructArray Limits