使用 StructArray 进行范围搜索

使用本页面对 StructArray 的向量子字段执行范围搜索。范围搜索会返回得分或距离落在指定边界范围内的向量匹配结果。对于 StructArray 字段,请结合元素级向量搜索使用范围搜索,此时每个 Struct 元素将独立进行搜索。

本页面使用来自“创建 StructArray 字段”中的 tech_articles Collection。该 Collection 包含一个名为chunks 的 StructArray 字段。其chunks[emb] 向量已针对元素级搜索进行了索引,可使用常规向量度量(如COSINEIPL2 )进行搜索。

范围搜索在 StructArray 中的应用

搜索模式范围搜索行为结果粒度
EmbeddingList 搜索不支持。不适用。
元素级搜索使用常规向量查询,配合 `radius ` 以及可选的 `range_filter`。结构元素级别。
混合搜索当 StructArray 请求针对元素级向量字段时支持。EmbeddingList 级请求不支持范围搜索。先进行元素级子搜索,然后进行混合重新排序。

如果您只需要最近的 Struct 元素,请先使用StructArray 进行基本向量搜索。当结果必须满足分数或距离边界(而非仅满足前 K 名排名)时,请使用范围搜索。

开始之前

在运行范围搜索之前,请准备好Collection、数据和索引。

要求详细信息
StructArray 字段Collection 包含一个 StructArray 字段,例如chunks
元素级向量子字段目标量子向量应为chunks[emb] ,而非chunks[emb_list_vector]
索引度量该向量子场使用常规向量度量进行索引,例如COSINEIPL2
查询数据查询对象是一个常规向量,而非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]`。

后续步骤

  1. 要了解 StructArray 的两种基本向量搜索模式,请阅读《使用 StructArray 进行基本向量搜索》。

  2. 若要向范围搜索添加标量过滤器,请阅读《使用 StructArray 进行过滤搜索》。

  3. 若在支持的情况下,希望每个父实体最多返回一个结果,请参阅《使用 StructArray 进行分组搜索》。

  4. 要查看特定版本的搜索限制,请阅读《StructArray 限制》。

翻译自DeepL

想要更快、更简单、更好用的 Milvus SaaS服务 ?

Zilliz Cloud是基于Milvus的全托管向量数据库,拥有更高性能,更易扩展,以及卓越性价比

免费试用 Zilliz Cloud
反馈

此页对您是否有帮助?