使用 StructArray 进行范围搜索
使用本页面对 StructArray 的向量子字段执行范围搜索。范围搜索会返回得分或距离落在指定边界范围内的向量匹配结果。对于 StructArray 字段,请结合元素级向量搜索使用范围搜索,此时每个 Struct 元素将独立进行搜索。
本页面使用来自“创建 StructArray 字段”中的 tech_articles Collection。该 Collection 包含一个名为chunks 的 StructArray 字段。其chunks[emb] 向量已针对元素级搜索进行了索引,可使用常规向量度量(如COSINE 、IP 或L2 )进行搜索。
范围搜索在 StructArray 中的应用
| 搜索模式 | 范围搜索行为 | 结果粒度 |
|---|---|---|
| EmbeddingList 搜索 | 不支持。 | 不适用。 |
| 元素级搜索 | 使用常规向量查询,配合 `radius ` 以及可选的 `range_filter`。 | 结构元素级别。 |
| 混合搜索 | 当 StructArray 请求针对元素级向量字段时支持。EmbeddingList 级请求不支持范围搜索。 | 先进行元素级子搜索,然后进行混合重新排序。 |
如果您只需要最近的 Struct 元素,请先使用StructArray 进行基本向量搜索。当结果必须满足分数或距离边界(而非仅满足前 K 名排名)时,请使用范围搜索。
开始之前
在运行范围搜索之前,请准备好Collection、数据和索引。
| 要求 | 详细信息 |
|---|---|
| StructArray 字段 | Collection 包含一个 StructArray 字段,例如chunks 。 |
| 元素级向量子字段 | 目标量子向量应为chunks[emb] ,而非chunks[emb_list_vector] 。 |
| 索引度量 | 该向量子场使用常规向量度量进行索引,例如COSINE 、IP 或L2 。 |
| 查询数据 | 查询对象是一个常规向量,而非EmbeddingList 。 |
有关索引设置,请参阅“索引 StructArray 字段”。
使用 radius 和 range_filter
设置 `radius ` 以定义搜索边界。若同时需要内部边界,请设置 `range_filter `。方向取决于“更小的距离”与“更高的相似度得分”何者更优。
| 度量类型 | 分数越高越好? | 使用range_filter 时的范围条件 |
|---|---|---|
L2 | 否。距离越小越好。 | range_filter <= distance < radius |
IP,COSINE | 是的。分数越大越好。 | radius < distance <= range_filter |
当仅设置radius 时,范围搜索会返回满足该度量外边界条件的匹配结果。请根据您Embeddings模型的分数或距离量表选择相应值。
执行元素级范围搜索
以下示例搜索那些其chunks[emb] 向量与查询向量足够相似的单个片段。每个匹配结果都代表一个匹配的Struct元素。
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 是一种相似度型度量,因此结果范围大于radius 且小于或等于range_filter 。返回时,offset 值用于标识chunks 数组中匹配的 Struct 元素。
添加标量过滤器
您可以将元素级范围搜索与 StructArray 标量过滤相结合。对父实体字段使用顶级谓词,并使用element_filter 来限制哪些 Struct 元素参与向量范围搜索。
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]",
],
)
顶级谓词用于筛选候选实体。element_filter 谓词则将向量范围搜索限制在匹配的Struct元素上。有关更多过滤示例,请参阅《使用StructArray进行过滤搜索》。
在混合搜索中使用范围搜索
StructArray 元素级向量字段支持在混合搜索中进行范围搜索。请将 `radius ` 以及(可选)`range_filter ` 添加到针对 StructArray 元素级向量字段的 `AnnSearchRequest ` 中。
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] 子请求使用了范围搜索参数。StructArray请求仍遵循元素级语义:在混合搜索合并并重新排序结果之前,范围边界适用于Struct元素的匹配结果。
解析范围搜索结果
| 结果项 | 含义 |
|---|---|
id | 包含匹配 Struct 元素的实体的主键。 |
distance 或得分 | 查询向量与匹配的 Struct 元素向量之间的得分或距离。 |
offset | 返回时,匹配的 Struct 元素在 StructArray 字段中的从零起算的位置。 |
| 重复的主键 | 可能发生。同一实体中的多个 Struct 元素可能落在指定范围内。 |
limit | 适用于元素命中,而非唯一的父实体。 |
限制
请勿对 StructArray 向量子域使用
EmbeddingList查询或MAX_SIM*指标进行范围搜索。EmbeddingList 级别的搜索不支持范围搜索。请勿将范围搜索与分组搜索结合使用。如果您需要为每个父实体返回一个结果,请执行不带范围参数的元素级搜索,并在支持的情况下使用分组功能。
StructArray 元素级向量字段支持混合范围搜索。但 EmbeddingList 级别的 StructArray 请求不支持此功能。
常见错误
对
chunks[emb_list_vector]执行范围搜索,而该指标专用于EmbeddingList搜索。在元素级范围搜索中使用
MAX_SIM_COSINE,而非常规指标(如COSINE)。使用
EmbeddingList查询代替常规向量查询。期望范围搜索结果按父实体唯一。范围搜索会返回匹配的 Struct 元素命中项。
使用 `
chunks.emb` 代替必需的子字段路径语法 `chunks[emb]`。
后续步骤
要了解 StructArray 的两种基本向量搜索模式,请阅读《使用 StructArray 进行基本向量搜索》。
若要向范围搜索添加标量过滤器,请阅读《使用 StructArray 进行过滤搜索》。
若在支持的情况下,希望每个父实体最多返回一个结果,请参阅《使用 StructArray 进行分组搜索》。
要查看特定版本的搜索限制,请阅读《StructArray 限制》。