写点什么

Elasticsearch 聚合学习之二:区间聚合,java 中高级面试题大全

用户头像
极客good
关注
发布于: 刚刚
  1. 《Elasticsearch聚合学习之二:区间聚合》

  2. 《Elasticsearch聚合学习之三:范围限定》;

  3. 《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 中的数据如下图:


本章概要

本篇实战的聚合操作有以下内容:


  1. 指定字段的区间聚合;

  2. 时间字段的区间聚合;

  3. 扩展实战;


接下来开始实战吧。

条形图(histogram 桶)

  1. 还记得 terms 桶么,用来将指定字段值相同的文档聚合在一个桶中,而 histogram 桶是将指定字段值在某个范围内的文档聚合在一个桶中,如下图所示,0-19999 是一个桶,11000 和 15000 在一个桶内,23000 和 31000 在一个桶内,这就是 histogram 桶:



  1. 以汽车销售记录为例做一次聚合查询,为售价创建 histogram 桶,以 20000 作为间隔,每个桶负责的区间如上图所示,相关的销售记录就会被放入对应的桶中,请求参数和说明如下:


GET /cars/transactions/_search


{


"size":0, ---令返回值的 hits 对象为空


"aggs":{ ---聚合命令


"price":{ ---聚合字段名称


"histogram": { ---桶类型


"field": "price", ---指定 price 字段的值作为判断条件


"interval": 20000 ---每个桶负责的区间大小为 20000


}


}


}


}


  1. es 返回的数据和说明如下:


{


"took" : 57,


"timed_out" : false,


"_shards" : {


"total" : 5,


"successful" : 5,


"skipped" : 0,


"failed" : 0


},


"hits" : {


"total" : 8,


"max_score" : 0.0,


"hits" : [ ]


},


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


"price" : { ---请求参数中指定的名称


"buckets" : [ ---price 桶的数据在此数组中


{


"key" : 0.0, ---第一个桶,区间[0-19999],0.0 是起始值


"doc_count" : 3 ---这个区间有三个文档(price 值分别是 10000、12000、15000)


},


{


"key" : 20000.0, ---第二个桶,区间[20000-39999],20000.0 是起始值


"doc_count" : 4 ---这个区间有四个文档


},


{


"key" : 40000.0, ---第三个桶,区间[40000-59999],40000.0 是起始值


"doc_count" : 0 ---这个区间没有文档


},


......

控制空桶是否返回

在上面的返回值中,第三个桶中没有文档,在有的业务场景中,我们不需要没有数据的桶,此时可以用 min_doc_count 参数来控制,如果 min_doc_count 等于 2,表示桶中最少有两条记录才会出现在返回内容中,如下所示,min_doc_count 如果等于 1,那么空桶就不会被 es 返回了:


GET /cars/transactions/_search


{


"size":0,


"aggs":{


"price":{


"histogram": {


"field": "price",


"interval": 20000,


"min_doc_count": 1


}


}


}


}


返回值如下所示,没有文档的桶不再出现:


{


"took" : 16,


"timed_out" : false,


"_shards" : {


"tota


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


l" : 5,


"successful" : 5,


"skipped" : 0,


"failed" : 0


},


"hits" : {


"total" : 8,


"max_score" : 0.0,


"hits" : [ ]


},


"aggregations" : {


"price" : {


"buckets" : [


{


"key" : 0.0,


"doc_count" : 3


},


{


"key" : 20000.0,


"doc_count" : 4


},


{


"key" : 80000.0,


"doc_count" : 1


}


]


}


}


}

histogram 桶加 metrics

  1. 上面的例子返回结果只有每个桶内的文档数,也可以加入 metrics 对桶中的数据进行处理,例如计算每个区间内的最高价、最低价、平均售价,可以加入 max、min、avg 参数,如下:


GET /cars/transactions/_search


{


"size":0, ---令返回值的 hits 对象为空


"aggs":{ ---聚合命令


"price":{ ---聚合字段名称


"histogram": { ---桶类型


"field": "price", ---指定 price 字段的值作为判断条件


"interval": 20000 ---每个桶负责的区间大小为 20000


},


"aggs": { ---表示对桶内数据做 metrics


"max_price": { ---指定 metrics 处理结果的字段名


"max":{ ---metrics 类型为 max


"field": "price" ---指定取 price 字段的值做最大值比较


}


},


"min_price": { ---指定 metrics 处理结果的字段名


"min":{ ---metrics 类型为 min


"field": "price" ---指定取 price 字段的值做最小值比较


}


},


"avg_price": { ---指定 metrics 处理结果的字段名


"avg":{ ---metrics 类型为 avg


"field": "price" ---指定取 price 字段的值计算平均值


}


}


}


}


}


}


  1. es 返回数据和说明如下,可见每个桶中的文档都做了三种 metrics 处理:


{


"took" : 17,


"timed_out" : false,


"_shards" : {


"total" : 5,


"successful" : 5,


"skipped" : 0,


"failed" : 0


},


"hits" : {


"total" : 8,


"max_score" : 0.0,


"hits" : [ ]


},


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


"price" : { ---请求参数中指定的名称


"buckets" : [ ---price 桶的数据在此数组中


{


"key" : 0.0, ---第一个区间[0-19999],0.0 是起始值


"doc_count" : 3, ---这个区间有三条记录(price 值分别是 10000、12000、15000)


"max_price" : { ---指定的 metrics 结果名称


"value" : 15000.0 ---桶中有三个文档,price 字段的最大值是 15000


},


"min_price" : {


"value" : 10000.0 ---桶中有三个文档,price 字段的最小值是 10000


},


"avg_price" : {


"value" : 12333.333333333334 ---桶中有三个文档,price 字段的平均值是 12333.333333333334


}


},


......

时间区间的桶(date_histogram)

  1. 按照时间区间聚合也是常用的功能,例如在 ELK 上查询日志,通常都是按照时间来分段的,如下图:



  1. histogram 桶可以实现按照时间分段么?如果用毫秒数来处理,似乎是可以的,但是对年月日的处理就力不从心了,常见的时间区间处理,用 date_histogram 桶即可满足要求;

  2. 下面就是 date_histogram 桶的用法:每月销售多少台汽车:


GET /cars/transactions/_search


{


"size": 0, ---令返回值的 hits 对象为空


"aggs": { ---聚合命令


"sales": { ---聚合字段名称


"date_histogram": { ---桶类型


"field": "sold", ---用 sold 字段的值作进行时间区间判断


"interval": "month", ---间隔单位是月


"format": "yyyy-MM-dd" ---返回的数据中,时间字段格式


},


"aggs": { ---表示对桶内数据做 metrics


"max_price": { ---指定 metrics 处理结果的字段名


"max":{ ---metrics 类型为 max


"field": "price" ---指定取 price 字段的值做最大值比较


}


},


"min_price": { ---指定 metrics 处理结果的字段名


"min":{ ---metrics 类型为 min


"field": "price" ---指定取 price 字段的值做最小值比较


}


}


}


}


}


}


  1. es 返回数据如下,篇幅所限因此略去了头部和尾部的一些信息,只看关键的:


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


"sales" : { ---请求参数中指定的名称


"buckets" : [ ---sales 桶的数据在此数组中


{


"key_as_string" : "2014-01-01", ---请求的 format 参数指定了 key 的格式


"key" : 1388534400000, ---真正的时间字段


"doc_count" : 1, ---2014 年 1 月份的文档数量


"max_price" : { ---2014 年 1 月的文档做了 metrics 类型为 max 的处理后,结果在此


"value" : 80000.0 ---2014 年 1 月的文档中,price 字段的最大值


},


"min_price" : { ---2014 年 1 月的文档做了 metrics 类型为 min 的处理后,结果在此


"value" : 80000.0 ---2014 年 1 月的文档中,price 字段的最大值

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Elasticsearch聚合学习之二:区间聚合,java中高级面试题大全