Elasticsearch使用Painless脚本过滤嵌套数组最后一个元素问题
问题原因
你当前的实现出错的核心原因是doc['warehouses.quantity']的取值逻辑不符合需求:
- 嵌套类型的字段在ES中会被拆分为独立的隐藏子文档存储,直接通过
doc取warehouses.quantity拿到的是所有嵌套子文档的quantity值的集合,和原始warehouses数组的对象没有对应关系 - ES的doc_values中存储的多值字段是默认排序的(数值型为升序),并非和原始数组的顺序一致,所以你调整下标拿到的也不是原数组最后一个嵌套对象的
quantity值,自然无法正确匹配所有符合条件的文档。
正确实现方案
要拿到原始warehouses数组的顺序和对象对应关系,需要从_source中读取原始文档内容,参考查询DSL如下:
GET /products/_search { "query": { "bool": { "filter": [ { "script": { "script": { "lang": "painless", "source": """ def warehouses = params._source.warehouses; if (warehouses == null || warehouses.size() == 0) { return false; } return warehouses[warehouses.size()-1].quantity == 123; """ } } } ] } } }
优化建议
- 脚本查询性能较低,如果你有大量这类查询需求,建议在数据写入时新增冗余字段
last_warehouse_quantity,直接写入warehouses最后一个元素的quantity值,后续查询直接用普通term查询匹配该字段即可,查询性能会提升数倍。 - 如果你的索引关闭了
_source存储,上述脚本方案无法使用,必须采用预写冗余字段的方案实现。
内容的提问来源于stack exchange,提问作者aniketk
相关产品推荐
相关产品推荐

