如何在Elasticsearch的script score中根据字段值条件执行数学公式
Elasticsearch 多属性分值计算解决方案
问题根因
你原有脚本存在两处错误导致逻辑不生效:
doc['A'].values返回的是数组类型,直接和单个数值做相等判断永远返回false,需调用Painless语法的contains()方法判断元素是否存在- 每个判断分支直接使用return语句,第一个分支执行完成后就会结束脚本,后续条件的计算逻辑永远不会执行
基础修正版(适配2个属性的场景)
GET /index/_search { "query": { "function_score": { "script_score": { "script": { "params": { "weight2": 5, "weight3": 4 }, "source": """ int total = 0; if (doc['A'].size() > 0) { if (doc['A'].values.contains(2)) { total += params.weight2; } if (doc['A'].values.contains(3)) { total += params.weight3; } } return total; """ } } } } }
注:增加doc['A'].size() > 0判断是为了兼容部分文档没有A字段的场景,避免空指针报错
批量属性优化方案(适配200+属性场景)
不需要写几百条判断语句,只需要把属性值和对应权重封装成参数Map,脚本内循环遍历累加即可,后续新增/修改属性只需要调整attributeWeight参数,不需要改动脚本逻辑:
GET /index/_search { "query": { "function_score": { "script_score": { "script": { "params": { "attributeWeight": { "2": 5, "3": 4 // 可以继续添加200+个属性和对应的权重,不需要改下面的脚本逻辑 } }, "source": """ int total = 0; if (doc['A'].size() > 0) { for (entry in params.attributeWeight.entrySet()) { int attrValue = Integer.parseInt(entry.getKey()); if (doc['A'].values.contains(attrValue)) { total += entry.getValue(); } } } return total; """ } } } } }
内容的提问来源于stack exchange,提问作者max04
相关产品推荐
相关产品推荐

