Elasticsearch条件字段脚本排序无返回结果问题排查
问题诊断与解决方案
核心问题分析
- 字段索引限制:从映射可见
name字段设置了index: false,该字段未被索引,无法通过doc['privatePerson.name']访问。即便尝试了keyword子字段,脚本的判断逻辑错误,导致排序失效。 - 嵌套对象判断逻辑错误:Elasticsearch的
doc上下文仅存储嵌套对象的叶子字段(如privatePerson.name.keyword),不会直接存储privatePerson这类父对象。你用doc.containsKey('privatePerson')和!doc['privatePerson'].empty的判断完全不生效,因为doc中不存在privatePerson这个键。
修正后的脚本实现
直接针对已索引的keyword子字段做判断,同时处理空值场景:
private String getFirstScript() { return "if (doc.containsKey('privatePerson.name.keyword') && doc['privatePerson.name.keyword'].size() > 0) {" + " return doc['privatePerson.name.keyword'].value;" + "} else if (doc.containsKey('legalPerson.companyName.keyword') && doc['legalPerson.companyName.keyword'].size() > 0) {" + " return doc['legalPerson.companyName.keyword'].value;" + "} else {" + " return '';" + "}"; }
额外注意事项
- 确保
legalPerson.companyName字段的映射同样包含已索引的keyword子字段,否则会出现相同的访问问题。 - 若业务允许,可将
name字段的index改为true,但keyword字段更适合精确字符串排序场景。 - Elasticsearch 6.x中,脚本排序需确保动态脚本权限开启(默认配置允许,若有安全限制需在
elasticsearch.yml中配置script.allowed_types: inline)。
验证方法
先在Kibana中执行带脚本排序的DSL查询,确认逻辑生效后再移植到Spring Data代码:
GET /people/companyindexeddata/_search { "sort": [ { "_script": { "type": "string", "script": { "inline": "if (doc.containsKey('privatePerson.name.keyword') && doc['privatePerson.name.keyword'].size() > 0) { return doc['privatePerson.name.keyword'].value; } else if (doc.containsKey('legalPerson.companyName.keyword') && doc['legalPerson.companyName.keyword'].size() > 0) { return doc['legalPerson.companyName.keyword'].value; } else { return ''; }" }, "order": "asc" } } ] }
内容的提问来源于stack exchange,提问作者Frankio1
相关产品推荐
相关产品推荐

