Elasticsearch如何配置参数化自定义脚本相似度实现稠密向量欧氏距离计算
结论
不用开发自定义插件的前提下,你期望的自定义脚本相似度绑定dense_vector字段的配置方式无法实现,核心原因如下:
- Elasticsearch的
scripted脚本相似度是为文本类型字段的分词打分场景设计的,执行上下文没有外部参数传入入口,你配置中用到的params.query_vector无法在查询时动态传入,会直接抛出参数不存在的异常。 dense_vector类型字段不支持绑定自定义脚本相似度,仅支持使用ES内置的cosine、dot_product、l2_norm三种相似度算法。
替代实现方案
不需要自定义插件,你可以选择以下两种方案实现相同效果,无需每次查询重复写计算公式:
方案1:使用存储脚本简化script_score查询
你可以将相似度计算逻辑预存为ES的全局存储脚本,查询时直接调用脚本ID即可:
- 首先创建存储脚本:
PUT _scripts/euclidean_sim_calc { "script": { "lang": "painless", "source": "1 / (1 + l2norm(params.query_vector, doc['embedding']))" } }
- 后续查询直接调用即可:
{ "size": 5, "query": { "script_score": { "query": {"match_all": {}}, "script": { "id": "euclidean_sim_calc", "params": {"query_vector": <MY_VECTOR>} } } } }
方案2:使用ES内置L2相似度的KNN查询(推荐)
7.3及以上版本的Elasticsearch原生支持基于L2距离的KNN查询,其默认返回的打分规则就是1/(1 + 欧氏距离),和你需要的计算逻辑完全一致,且KNN查询性能远高于全表扫描的script_score方案:
- 索引配置直接用内置l2_norm相似度即可,无需自定义脚本:
{ "mappings": { "properties": { "@id": { "type": "keyword" }, "embedding": { "dims": 128, "type": "dense_vector", "index": true, "similarity": "l2_norm" } } } }
- 查询时直接调用KNN接口,传入向量参数即可:
{ "size": 5, "knn": { "field": "embedding", "query_vector": <MY_VECTOR>, "k": 5, "num_candidates": 100 } }
内容的提问来源于stack exchange,提问作者Eugenia Oshurko
相关产品推荐
相关产品推荐

