Elasticsearch如何按reviews数组中positive_comment字段长度排序
ES数组内部评论字段按长度排序解决方案
问题根因
- 你当前使用的文档级sort脚本作用于整个文档,不会改变返回结果中
reviews数组的内部元素顺序 - ES默认会打平普通object数组的所有属性,
doc['reviews.positive_comment']返回的是整个文档所有评论的positive_comment值集合,不是单个评论的字段值,计算出的长度自然不符合预期 - 空字符串的原生长度为0,升序排序会默认排在最前面,需要单独处理空值的排序权重
解决方案
方案1:reviews为nested类型(推荐)
如果你的索引中reviews字段已设为nested类型(数组对象的标准存储方案),使用nested聚合+top_hits排序实现需求:
{ "query": { "bool": { "filter": [ {"term": {"id": 214}} ] } }, "_source": false, "aggs": { "reviews_nested": { "nested": { "path": "reviews" }, "aggs": { "sorted_reviews": { "top_hits": { "sort": [ { "_script": { "type": "number", "script": "def comment = doc['reviews.positive_comment'].value; return comment.isEmpty() ? 99999 : comment.length();", "order": "asc" } } ], "_source": ["reviews.positive_comment", "reviews.negative_comment", "reviews.reviewer_name"], "size": 100 } } } } } }
说明:
- 脚本中将空字符串的排序权重设为99999(远大于正常评论长度即可),即可实现空评论排在最后
- 调整
size参数适配你需要返回的最大评论数量
方案2:reviews为普通object数组
无需修改索引映射,直接通过script_fields读取原始数组手动排序:
{ "_source": ["id"], "query": { "bool": { "filter": [{"term": {"id": 214}}] } }, "script_fields": { "sorted_reviews": { "script": """ def reviews = params._source.reviews; reviews.sort((a, b) -> { def lenA = a.positive_comment.length(); def lenB = b.positive_comment.length(); lenA = lenA == 0 ? 99999 : lenA; lenB = lenB == 0 ? 99999 : lenB; return lenA.compareTo(lenB); }); return reviews; """ } } }
排序后的评论会直接返回在sorted_reviews字段中。
内容的提问来源于stack exchange,提问作者JuanCruz
相关产品推荐
相关产品推荐

