如何为Elasticsearch响应新增字段并获取搜索词与结果的相似度指标
Elasticsearch新增相似度返回字段解决方案
不需要开发自定义插件或者新增REST handler,Elasticsearch原生提供了多种实现方案,可按需选择:
方案1:搜索pipeline(推荐,7.13+版本支持)
这是对业务侧侵入最小的方案,你可以提前创建一个全局的搜索响应处理流水线,自动为所有指定使用该流水线的查询结果插入归一化的相似度字段,无需修改业务查询逻辑:
- 创建搜索pipeline,内置响应处理器自动计算0-1区间的相似度值:
PUT _search/pipeline/add_normalized_similarity { "response_processors": [ { "script": { "source": """ def maxScore = ctx.hits.max_score; for (hit in ctx.hits.hits) { hit.fields.similarity = maxScore != null && maxScore > 0 ? hit._score / maxScore : 0f; } """ } } ] }
- 查询时指定使用该pipeline即可自动返回相似度字段:
GET your_index/_search?search_pipeline=add_normalized_similarity { "query": { "match": { "username": "john" } } }
返回的结果每条命中记录的fields.similarity就是你需要的0-1区间的相似度指标。
方案2:runtime fields/script_fields(全版本支持)
如果你的ES版本低于7.13,可以在查询时通过脚本字段直接计算返回:
GET your_index/_search { "query": { "match": { "username": "john" } }, "script_fields": { "similarity": { "script": { "source": "return _score / params.max_possible_score", "params": { "max_possible_score": 12.0 // 可替换为你提前测算的该查询场景的最大理论得分 } } } } }
如果要做动态归一化,也可以先发起一次查询拿到本次的max_score,再第二次查询带入参数计算即可。
方案3:应用层处理
如果不想修改ES侧任何配置,直接在应用层拿到搜索响应后,用返回的max_score对每条结果的_score做归一化计算即可,实现成本最低。
只有当你的相似度计算逻辑非常特殊,原生脚本实现无法满足性能要求时,才需要考虑开发自定义插件,90%以上的常规场景用上述原生方案即可满足需求。
内容的提问来源于stack exchange,提问作者Umut Can Alaçam
相关产品推荐
相关产品推荐

