Elasticsearch 原生 dense_vector 字段不支持在插件配置文件中设置全局相似度阈值,相似度过滤需要在搜索请求中通过 min_score 参数或脚本查询动态控制。
先说结论:向量相似度阈值属于查询时的业务逻辑,不存在静态的插件配置项。
- 适合:使用 native dense_vector 字段类型的场景
- 先准备:确认 mapping 中定义的 similarity 算法类型
- 验收:检查搜索响应 hits 中的 _score 是否符合预期范围
命令速用版
在搜索请求中使用 min_score 参数过滤低相似度结果,以下示例展示如何设置最低得分阈值。
GET /my-index/_search
{
"min_score": 0.75,
"query": {
"knn": {
"field": "my_vector",
"query_vector": [0.1, 0.2, 0.3],
"k": 10,
"num_candidates": 100
}
}
}如果使用的是 script_score 查询,可以在脚本中编写具体的相似度计算逻辑并返回分数,低于阈值的结果不会满足查询条件。
为什么会这样
向量相似度是查询向量与文档向量实时计算得出的动态值,无法预先固化在配置文件中。Elasticsearch 的向量检索机制依赖于查询时传入的 query_vector,不同查询向量产生的最高分和分布完全不同,因此全局固定阈值没有实际意义。
分步处理
第一步是定义映射,创建索引时指定 dense_vector 字段及相似度算法,cosine 适合归一化数据,dot_product 适合未归一化数据。
PUT /my-index
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3,
"similarity": "cosine"
}
}
}
}第二步是写入向量数据,确保存入的向量维度与 mapping 定义一致,否则写入会报错。
第三步是执行查询,根据业务容忍度在 search API 中设置 min_score 或使用 range 查询过滤 _score 字段,注意 min_score 会提前终止部分低分段的搜索以提升性能。
怎么验证是否生效
检查搜索响应 body 中的 hits.hits 数组,确认所有返回文档的 _score 字段值均大于或等于设定的阈值。
同时观察 hits.total 数量,如果设置阈值后数量明显减少,说明过滤逻辑正在工作;如果数量未变但分数偏低,需检查相似度算法是否与数据预处理方式匹配。
常见坑
不同 similarity 算法的分值范围不同,cosine 相似度通常在 0 到 1 之间,而 dot_product 可能为负数或大于 1,直接套用阈值会导致过滤失效。
min_score 参数在某些聚合查询或复杂嵌套查询中可能不被支持,此时需要改用 script_score 在查询内部进行分数截断。
向量维度不匹配会导致索引写入失败或查询报错,生产环境变更前需在测试索引验证 dims 参数。
常见问题
能全局配置默认相似度阈值吗?
不能,Elasticsearch 没有全局配置文件支持该参数,必须在每次搜索请求中指定。
cosine 和 dot_product 怎么选?
如果向量数据已经归一化处理,优先选 dot_product 性能更好,否则选 cosine 更稳妥。
阈值设多少合适?
公开资料中没有看到可靠的量化数据,需根据业务场景对召回率和准确率的权衡通过测试确定。
参考来源
- Elasticsearch Guide, Dense vector field type, https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector-field-type.html
- Elasticsearch Guide, KNN search, https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html