Elasticsearch聚合学习之二:区间聚合

“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” : {

“total” : 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字段的最大值

}

},

{

“key_as_string” : “2014-02-01”,

“key” : 1391212800000,

“doc_count” : 1,

“max_price” : {

“value” : 25000.0

},

“min_price” : {

“value” : 25000.0

}

},

  1. 上面的请求是以一个月作为区间的,如果想以其他时间单位作为区间又该怎么做呢?例如90天,把interval字段写成90d即可,其他粒度的时间间隔写法如下表:

| 表达式 | 含义 |

| — | — |

| 1y | 一年(数量只能是1,例如2y不合法) |

| 1q | 一个季度(数量只能是1,例如2q不合法) |

| 1M | 一个月(数量只能是1,例如2M不合法,注意区分大写,M表示月,m表示分钟) |

| 1w | 一周(数量只能是1,例如2w不合法) |

| 2d | 两天(数量可以是整数类型) |

| 3h | 三个小时(数量可以是整数类型) |

| 4m | 四分钟(数量可以是整数类型,注意区分大写,M表示月,m表示分钟) |

| 5s | 五秒钟(数量可以是整数类型) |

注意:年、季度、月、周都的数量只能是1,其他粒度的数量可以是整数;

例如以90天作为区间来聚合,请求参数如下:

GET /cars/transactions/_search

{

“size”: 0,

“aggs”: {

“sales”: {

“date_histogram”: {

“field”: “sold”,

“interval”: “90d”, -------表示以90天作为间隔

“format”: “yyyy-MM-dd”

},

“aggs”: {

“max_price”: {

“max”:{

“field”: “price”

}

},

“min_price”: {

“min”:{

“field”: “price”

}

}

}

}

}

}

date_histogram的空桶处理

date_histogram也支持min_doc_count参数,和histogram桶的用法一样,对于下面的请求,es的响应中不会有空桶:

GET /cars/transactions/_search

{

“size”: 0,

“aggs”: {

“sales”: {

“date_histogram”: {

“field”: “sold”,

“interval”: “1M”,

“format”: “yyyy-MM-dd”,

“min_doc_count”: 1

}

}

}

}

扩展实战

  1. 本篇的最后,来做一个略为复杂的聚合操作:按季度展示每个汽车品牌的销售总额;

  2. 显然,操作的第一步是按照时间区间做聚合,然后在每个桶中,将文档按照品牌做第二次聚合,第二次聚合的结果也可以理解为多个桶,每个桶中的文档,是某个平台在某个季度的销售总额;

  3. 请求如下:

GET /cars/transactions/_search

{

“size”: 0, —令返回值的hits对象为空

“aggs”: { —聚合命令

“sales”: { —聚合字段名称

“date_histogram”: { —桶类型为时间区间

“field”: “sold”, —指定sold字段的值作为判断条件

“interval”: “1q”, —区间间隔为1季度

“format”: “yyyy-MM-dd”, —返回的桶的key,被格式化时的格式

“min_doc_count”: 1 —空桶不返回

},

“aggs”: { —第二层桶

“per_make_sum”: { —聚合字段名称

“terms”: { —桶类型为terms

“field”: “make” —按照make字段聚合

},

“aggs”: { —第二层桶的metrics

“sum_price”: { —聚合字段名称

“sum”: { —metrics处理,累加

“field”: “price” —取price字段的值累加

}

}

}

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

}

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-6AE5O88S-1715671320325)]

[外链图片转存中…(img-Mww3tOQ8-1715671320326)]

[外链图片转存中…(img-AodMYvbE-1715671320326)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值