如何使用Python-Milvus向量数据库进行向量范围搜索?

摘要:Milvus 向量数据库实践:范围搜索(Range Search)详解 在构建基于向量检索的应用时,我们通常需要从海量向量中找到与查询向量最相似的 Top-K 个结果。然而,在某些场景下,我们不仅需要“最相似”的结果,还需要对相似度设置一个
Milvus 向量数据库实践:范围搜索(Range Search)详解 在构建基于向量检索的应用时,我们通常需要从海量向量中找到与查询向量最相似的 Top-K 个结果。然而,在某些场景下,我们不仅需要“最相似”的结果,还需要对相似度设置一个阈值范围,只返回相似度在一定区间内的向量。这就是范围搜索(Range Search)的用武之地。 范围搜索的核心:radius 与 range_filter 范围搜索不同于传统的 Top-K 检索,它允许你划定一个距离区间,只返回落在这个区间内的向量。但距离的含义取决于所选的度量类型。Milvus 支持多种距离度量,如欧氏距离(L2)、内积(IP)、余弦距离(COSINE)等。不同的度量类型对 radius 和 range_filter 的语义和取值要求不同。 Milvus 中 COSINE 度量返回的是余弦相似度 在 Milvus 中: metric_type="COSINE" 计算的是余弦相似度(Cosine Similarity),而不是余弦距离。 余弦相似度的取值范围是 [-1, 1](当向量被归一化后,取值范围为 [0, 1],因为非负向量内积非负)。值越大表示两个向量越相似,最大值为 1(向量完全相同)。 对于 COSINE 度量,Milvus 要求: range_filter 必须大于 radius,否则会触发断言错误。这是因为区间定义为 (radius, range_filter],即距离大于 radius 且小于等于 range_filter。如果 range_filter ≤ radius,区间为空或逻辑错误。 在示例中: radius = 0.4:过滤掉距离 ≤ 0.4 的高相似度结果(因为距离越小越相似,所以距离 ≤ 0.4 意味着余弦相似度很高,可能接近于1)。 range_filter = 0.9:过滤掉距离 > 0.9 的低相似度结果。 最终返回的是余弦距离在 (0.4, 0.9] 之间的向量。 为什么要有这个限制? 假设你想找出所有与查询向量“比较相似但不完全一致”的向量,就可以设置一个下限(例如 0.4),排除掉那些过于相似的(可能包含查询自身或重复数据),同时设置一个上限(例如 0.9),排除掉那些不太相关的。这种灵活的区间控制在实际业务中非常有用,例如去重、异常检测、多样性采样等。 注意事项 集合必须加载:执行 search 前务必调用 load_collection,否则会报错。 度量类型一致性:search_params 中的参数解释依赖于集合创建时指定的度量类型。如果不确定,可以通过 describe_collection 查看。 参数顺序与逻辑:对于 COSINE 度量,务必确保 range_filter > radius。对于其他度量(如 L2),规则可能不同,需参考官方文档。 范围与 limit 的关系:范围搜索先根据区间过滤,然后从符合条件的结果中取前 limit 个。如果区间内结果不足 limit,则返回实际数量(可能少于 limit)。 性能考虑:范围搜索需要扫描满足距离条件的向量,相比普通 Top-K 可能略慢,但在合理索引支持下仍能高效执行。 代码: import warnings warnings.filterwarnings("ignore", message=".*pkg_resources is deprecated as an API.*") from pymilvus import MilvusClient # 初始化 Milvus 客户端连接 # uri: Milvus 服务的 HTTP 地址和端口(单机版默认 19530) # token: 认证令牌,格式为 "用户名:密码"(默认管理员账号 root,密码 Milvus) client = MilvusClient( uri="http://192.168.211.128:19530", token="root:Milvus" ) # 加载指定集合到内存(Milvus 检索前必须执行的关键步骤) # 集合默认处于离线状态,未加载会报"集合找不到"错误 # collection_name: 目标集合名称(已提前创建并插入数据的 data_t 集合) client.load_collection(collection_name="data_t") # 定义待查询的 5 维向量(需与集合中存储的向量维度一致) # 该向量对应集合中 id=0 的向量,用于相似度检索 query_vector = [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592] # 执行向量范围搜索(核心操作) # collection_name: 要检索的目标集合 # data: 待检索的向量列表(支持批量检索,此处仅传 1 个向量) # limit: 返回符合条件的相似度最高的前 3 条结果(Top3) # search_params: 范围搜索参数(针对 COSINE 度量的特殊规则) # params.radius: 距离下限(COSINE 类型下,只保留距离 > 0.4 的结果) # params.range_filter: 距离上限(COSINE 类型下,只保留距离 ≤ 0.9 的结果) # 关键规则:COSINE 度量必须满足 range_filter > radius,否则会触发断言报错 res = client.search( collection_name="data_t", data=[query_vector], limit=3, search_params={ "params": { "radius": 0.4, # 下限:过滤掉距离 ≤ 0.4 的高相似度结果 "range_filter": 1 # 上限:过滤掉距离 > 0.9 的低相似度结果 } }, output_fields = ["color", "likes"] ) # 遍历并打印检索结果 # res 是列表,每个元素对应一个查询向量的检索结果(此处仅 1 个查询向量) for hits in res: print("TopK results:") # 打印 TopK 结果提示 # 遍历当前查询向量的每一条命中结果 for hit in hits: # hit 字典包含 3 部分: # id: 向量主键 ID # distance: 与查询向量的余弦距离(值越小相似度越高,范围 [0,2]) # entity: 由 output_fields 指定的字段数据(color、likes) print(hit) 结果如下: {'id': 0, 'distance': 1.0, 'entity': {'color': 'pink_8682', 'likes': 165}} {'id': 1, 'distance': 0.6290165185928345, 'entity': {'color': 'red_7025', 'likes': 25}} {'id': 4, 'distance': 0.5975796580314636, 'entity': {'color': 'red_4794', 'likes': 122}} 更多学习资料尽在老虎网盘资源: 老虎网盘资源