Elasticsearch 6.4嵌套字段内部排序及文档按cost降序求助
嘿,这个需求我刚好碰到过类似的,在Elasticsearch 6.4里可以通过**脚本字段(script field)**来实现,既满足文档按cost降序排序,又能让每个文档里的dirs数组内部按date_by做nulls-first排序,我给你详细拆解一下:
解决方案步骤
首先明确你的两个核心需求:
- 整个文档集合按
cost字段降序排列; - 每个文档返回时,内部的
dirs数组按date_by字段以nulls-first规则排序(null值排在最前面),但不用这个嵌套字段排序文档本身。
针对这两个需求,我们可以结合Elasticsearch的sort和script_fields来实现:
1. 文档级排序:按cost降序
这部分很直接,在查询的sort参数里指定cost字段的排序规则即可:
"sort": [{"cost": "desc"}]
2. 嵌套数组内部排序:dirs按date_by nulls-first排序
因为Elasticsearch默认不会自动排序返回的嵌套数组,我们需要用Painless脚本在查询时对每个文档的dirs数组进行排序,通过script_fields来生成排序后的字段(或者覆盖原字段)。
完整查询示例
{ "sort": [ {"cost": "desc"} ], "script_fields": { "dirs": { "script": { "lang": "painless", "source": """ // 获取原始的dirs数组 List<Map> dirList = params._source.dirs; // 自定义排序逻辑:nulls-first,非null按日期升序(可根据需求调整) dirList.sort((dirA, dirB) -> { String dateA = dirA.date_by; String dateB = dirB.date_by; // 两个都是null,顺序不变 if (dateA == null && dateB == null) { return 0; } // dateA为null,排前面(nulls-first) if (dateA == null) { return -1; } // dateB为null,dateA排后面 if (dateB == null) { return 1; } // 都不为null,按日期字符串比较(yyyy-MM-dd格式字典序和日期顺序一致) return dateA.compareTo(dateB); }); return dirList; """ } }, // 其他需要返回的字段(比如cost、_id) "cost": { "script": "return params._source.cost" }, "_id": { "script": "return params._source._id" } }, // 关闭原始_source返回,只返回我们定义的script_fields "_source": false }
关键细节解释
- 脚本逻辑:我们直接从
params._source获取原始的dirs数组(保证拿到完整的嵌套对象结构),然后用自定义比较器实现nulls-first的排序规则——因为你的日期是yyyy-MM-dd格式,字符串的字典序和实际日期顺序一致,所以直接用compareTo即可。 - 字段返回:因为设置了
_source: false,我们需要把需要返回的其他字段(比如cost、_id)也通过script_fields定义,如果你需要保留更多原始字段,可以调整_source为true或者使用_source.includes指定字段,同时保留dirs的脚本字段。 - 性能注意:如果你的数据量很大,查询时用脚本排序数组会有一定性能开销。如果这个排序规则是固定的,也可以考虑在索引阶段就用Ingest Pipeline的
sortprocessor对dirs数组排序,这样查询时就不需要额外处理了。
验证结果
用你提供的测试数据,执行这个查询后,返回的结果会是:
- 文档2(cost=200)排在文档1(cost=100)前面;
- 文档2的
dirs数组会按date_bynulls-first排序:dir_id=3(date_by=null)、dir_id=5(date_by=null)、dir_id=4(date_by="2016-01-01"); - 文档1的
dirs数组会是:dir_id=2(date_by=null)、dir_id=1(date_by="2018-12-01")。
内容的提问来源于stack exchange,提问作者Евгений Залужанский
相关产品推荐
相关产品推荐

