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] 向量子字段已针对元素级搜索创建索引,并使用常规向量度量类型,例如 COSINE、IP 或 L2。
How range search applies to StructArray
| Search mode | Range search 行为 | 结果粒度 |
|---|---|---|
| EmbeddingList search | 不支持。 | 不适用。 |
| Element-level search | 使用常规向量查询,并指定 radius,也可以选择指定 range_filter。 | Struct 元素级别。 |
| 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 field | Collection 包含一个 StructArray field,例如 chunks。 |
| 元素级 vector subfield | 目标 vector subfield 是 chunks[emb],而不是 chunks[emb_list_vector]。 |
| Index metric | vector subfield 使用常规 vector metric 建立 Index,例如 COSINE、IP 或 L2。 |
| Query data | Query 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 的分数或距离尺度选择取值。
Run element-level Range Search
以下示例会搜索单个 chunk,其 chunks[emb] 向量与查询向量足够相似。每个结果 hit 表示一个匹配的 Struct element。
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。
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。
在 Hybrid Search 中使用 Range Search
StructArray 元素级向量字段支持在 Hybrid Search 中使用 Range Search。请在面向 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] 子请求使用 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。 -
使用
EmbeddingListquery,而不是常规 vector query。 -
期望 Range Search 结果按父 Entity 去重。Range Search 返回匹配的 Struct 元素命中。
-
使用
chunks.emb,而不是必需的子字段路径语法chunks[emb]。
后续步骤
-
要了解两种基本的 StructArray vector search 模式,请阅读 Basic Vector Search with StructArray。
-
要为 range search 添加 scalar filter,请阅读 Filtered Search with StructArray。
-
要在支持的情况下为每个父 Entity 最多返回一条结果,请阅读 Grouping Search with StructArray。
-
要查看特定版本的 search 限制,请阅读 StructArray Limits。