0
点赞
收藏
分享

微信扫一扫

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

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《Elasticsearch聚合学习》系列的第四篇,在前面的实战中,聚合的结果以桶(bucket)为单位,放在JSON数组中返回,这些数据是没有排序的,今天来学习如何给这些数据进行排序;

系列文章列表

  1. 《Elasticsearch聚合学习之一:基本操作》;
  2. 《Elasticsearch聚合学习之二:区间聚合》;
  3. 《Elasticsearch聚合学习之三:范围限定》;
  4. 《理解elasticsearch的post_filter》;

环境信息

  • 以下是本次实战的环境信息,请确保您的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自身也内置了两种排序参数,可以直接拿来使用:
  • _count:这个参数对应的就是doc_count,以下请求的排序效果和默认的排序效果是一致的:
GET /cars/transactions/_search
{
size:0,
aggs:{
popular_colors:{
terms: {
field: color,
order: { ---表示要对聚合结果做排序
_count: desc ---排序字段是doc_count,顺序是降序
}
}
}
}
}
  • _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的首字母升序排序: 在这里插入图片描述

  • 另外《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 : { ---桶名称
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: {
terms: { ---桶类型是terms
field: make, ---按照make字段聚合
order: { ---要求排序
stat.avg: asc ---排序字段是metrics结果的一个子项(平均值),升序
}
},
aggs: {
stat: { ---metrics处理后的结果保存在名为stat的字段中,排序已经指定了该字段的agv子项(平均值)
extended_stats: { ---桶内的metrics处理,类型是计算数量、最大值、最小值、平均值等多个指标项
field: price ---将price字段的值拿来做metrics处理
}
}
}
}
}
}
  • 返回结果如下,可见已经按照metrics结果的avg子项做了升序排序:
......
aggregations : {
sales_rank : {
doc_count_error_upper_bound : 0,
sum_other_doc_count : 0,
buckets : [
{
key : toyota,
doc_count : 2,
stat : {
count : 2,
min : 12000.0,
max : 15000.0,
avg : 13500.0, ---排序字段
sum : 27000.0,
sum_of_squares : 3.69E8,
variance : 2250000.0,
std_deviation : 1500.0,
std_deviation_bounds : {
upper : 16500.0,
lower : 10500.0
}
}
},
{
key : honda,
doc_count : 3,
stat : {
count : 3,
min : 10000.0,
max : 20000.0,
avg : 16666.666666666668, ---排序字段
sum : 50000.0,
sum_of_squares : 9.0E8,
variance : 2.222222222222221E7,
std_deviation : 4714.045207910315,
std_deviation_bounds : {
upper : 26094.757082487296,
lower : 7238.5762508460375
}
}
},
......

嵌套桶排序

  • 在聚合查询中,经常对聚合的数据再次做聚合处理,例如统计每个汽车品牌下的每种颜色汽车的销售额,这时候DSL中就有了多层aggs对象的嵌套,这就是嵌套桶(此名称来自《Elasticsearch 权威指南》,如下图所示:

在这里插入图片描述

  • 嵌套桶的排序情况略为复杂,详情请参考《Elasticsearch聚合的嵌套桶如何排序》;

  • 至此,聚合返回结果排序的实战已经完成了,后面的章节会深入学习es的聚合有关的关键知识点;

欢迎关注51CTO博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

举报

相关推荐

0 条评论