写点什么

Elasticsearch 聚合学习之四:结果排序

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:1933 字

    阅读完需:约 6 分钟

  1. 《Elasticsearch聚合学习之四:结果排序》

环境信息

以下是本次实战的环境信息,请确保您的 Elasticsearch 可以正常运行:


  1. 操作系统:Ubuntu 18.04.2 LTS

  2. JDK:1.8.0_191

  3. Elasticsearch:6.7.1

  4. Kibana:6.7.1


实战用的数据依然是一些汽车销售的记录,在第一章有详细的导入步骤,请参考操作,导入后您的 es 中的数据如下图:



接下来一起实战聚合排序吧;

默认排序

之前文章中的聚合查询,我们都没有做排序设置,此时 es 会用每个桶的 doc_count 字段做降序,下图是个 terms 桶聚合的示例,可见返回了三个 bucket 对象,是按照 doc_count 字段降序排列的:


内置排序

除了自定义排序,es 自身也内置了两种排序参数,可以直接拿来使用:


  1. _count:这个参数对应的就是 doc_count,以下请求的排序效果和默认的排序效果是一致的:


GET /cars/transactions/_search


{


"size":0,


"aggs":{


"popular_colors":{


"terms": {


"field": "color",


"order": { ---表示要对聚合结果做排序


"_count": "desc" ---排序字段是 doc_count,顺序是降序


}


}


}


}


}


  1. _key:在区间聚合的时候(histogram 或者 date_histogram),可以根据桶的 key 做排序:


GET /cars/transactions/_search


{


"size": 0,


"aggs": {


"price": {


"histogram": { ---区间聚合


"field": "price", ---取 price 字段的值


"interval": 20000, ---每个区间的大小是 20000


"order": { ---表示要对聚合结果做排序


"_key": "desc" ---排序字段是桶的 key 值,这里是每个区间的起始值,顺序是降序


}


}


}


}


}


返回结果如下,已经按照 key 的大小从大到小排序:


......


"aggregations" : {


"price" : {


"buckets" : [


{


"key" : 80000.0,


"doc_count" : 1


},


{


"key" : 60000.0,


"doc_count" : 0


},


{


"key" : 40000.0,


"doc_count" : 0


},


{


"key" : 20000.0,


"doc_count" : 4


},


{


"key" : 0.0,


"doc_count" : 3


}


]


}


}


}


《Elasticsearch 权威指南》里指出:_key 只在 histogram 和 date_histogram 内使用,原文如下图红框所示:



但是在实际操作中发现,6.7.1 版本中,除了 histogram 和 date_histogram,terms 桶也可以用_key 排序,如下图,是按照 key 的字母降序:



把 desc 改为 asc 之后返回如下图,变成了按照 key 的首字母升序排序:



3. 另外《Elasticsearch 权威指南》中还提到一种内置排序类型_term,但是《Elasticsearch官方文档》中宣布该类型在 6.0 之后已经废弃,如下:



也许是"手贱"的缘故,我还是用_term 试了下,可以返回结果,但是会建议用_key 替代_term,如下图:


按照 metrics 排序(metrics 结果只有一个值)

常见的 metrics 有累加和(sum)、最大值(max)、最小值(min)、平均值(avg),这些 metrics 的特点是处理结果只有一个值,我们可以按照这个结果来排序,例如计算每个汽车品牌的销售额,再按照销售额排序:


GET /cars/transactions/_search


{


"size": 0,


"aggs": {


"sales_rank": {


"terms": { ---桶类型是 terms


"field": "make", ---按照 make 字段聚合


"order": { ---要求排序


"sales": "desc" ---排序字段是 sales


}


},


"aggs": {


"sales": { ---metrics 处理后的结果保存在名为 sales 的字段中,排序已经指定了该字段


"sum": { ---桶内的 metrics 处理,类型是累加


"field": "price" ---将 price 字段的值累加


}


}


}


}


}


}


下面是聚合结果,可见已按照每个品牌的销售额大小做了降序的排序:


......


"aggregations" : { ---聚合结果


"sales_rank" : {


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


             ---桶名称
复制代码


"doc_count_error_upper_bound" : 0,


"sum_other_doc_count" : 0,


"buckets" : [ ---这个 JSON 数组内是按照品牌聚合而成的所有桶


{


"key" : "bmw", ---品牌为 bmw 的桶


"doc_count" : 1, ---文档数量为 1


"sales" : { ---metrics 处理结果


"value" : 80000.0 ---品牌为 bmw 的汽车销售总额是 80000


}


},


{


"key" : "ford",


"doc_count" : 2,


"sales" : {


"value" : 55000.0


}


},


{


"key" : "honda",


"doc_count" : 3,


"sales" : {


"value" : 50000.0


}


},


{


"key" : "toyota",


"doc_count" : 2,


"sales" : {


"value" : 27000.0


}


}


]


}


}


}

按照 metrics 排序(metrics 结果有多个值)

和 sum、max 这些只有一个结果的 metrics 不同,extended_stats 的结果包含了数量、最大值、最小值、平均值、累加和等多种处理,此时必须要指定用其中的哪一项(否则会返回错误:Invalid aggregation order path [xxxx]. When ordering on a multi-value metrics aggregation a metric name must be specified):


GET /cars/transactions/_search


{


"size": 0,


"aggs": {


"sales_rank": {

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
Elasticsearch聚合学习之四:结果排序