elk笔记16--aggs-Bucket Aggregations
本文对聚合中的bucket类型聚合进行进一步介绍,包括基础概念、常见aggs案例、注意事项等部分,后续将在此模块持续补充完善bucket类型的aggs。
1 Bucketing 简介
在桶聚合中,一组聚合构成了多个桶,每个桶与一个关键字、一个文档规则相关联。当一个聚合被执行后,所有的桶规则都会对每一文档进行评估,如果匹配到了某个规则,该文档就会被放到对应桶中。聚合完成后,将会得到一组桶,每个桶里面都会有属于它的文档集。
Bucket 聚合并不会想指标聚合一样在字段上计算属性,它只创建很多文档的桶。每个bucket与一个规则相关联,该规则决定了一个文档是否在某个桶中。换句话说,buckets很高效地定义了文档集合。除了buckets自己外,bucket聚合也计算并返回bucket的文档数量。
与指标聚合相反,bucket聚合可以包含子聚合。子聚合根据其父bucket聚合的bucket文档,可以进一步聚合出一系列文档集合。
es 中有很多不同类型的bucket聚合,每一个都有不同的桶策略。一些定义了单个bucket,一些定义了固定数量的多buckets,还有一些bucket聚合在聚合过程中动态创建buckets。
需要注意的是:es中单次返回的最大桶数量默认为10000,该值可以通过集群参数search.max_buckets来设置,如果返回的桶数量超过该值就会报错。
2 Bucket Aggregations 分类
2.1 Terms Aggregation
terms 聚合即为按照某个字段聚合,例如按照客户聚合,则相同客户所有的订单将构成一个bucket;
GET kibana_sample_data_ecommerce/_search
{
"aggs": {
"group_by_user": {
"terms": {
"field": "user",
"size": 2
}
}
},
"size": 0
}
输出:
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"group_by_user" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 12417,
"buckets" : [
{
"key" : "elyssa",
"doc_count" : 1044
},
{
"key" : "abd",
"doc_count" : 564
}
]
}
}
}
此处最外层size为0的时候将不返回匹配到数据的信息;
field同层的size为2,表示返回订单数量最多的2个用户的数据;
注意:当terms中设置了size后,aggs->terms 获取的数据不一定是准确,因为terms只获取每个shard中的top size个记录,然后对获取的记录进行聚合,而不是对所有的字段聚合后再全局排序。
假如有3个shard, user的size为2,shard中可以统计不同用户购物次数,a1[50] 表示a1 在shard中出现了50次购物记录;
shard A | shard B | shard C |
---|---|---|
a1[50], a2[40] | b1[51], b2[41] | c1[52], c2.[42] |
d[30] | d[30] | e[20] |
由于size为2,所以每个shard只返回其top2 的数据,即为此次返回a1,a2,b1,b2,c1,c2,再对它们进行排序得到b1和c1 2个记录;理论上shard A 和shard B中d的总次数为60为全局最大,但是由于es的计算方式,导致d并未被返回,因此出现了不准确的现象。
针对这个问题,我们可以通过提高size的值来提高准确性,但是size过大会导致较大的计算量和资源开销,会影响性能。
因此,在实际业务中我们需要综合考虑准确性和查询性能,按照需求加以平衡即可。
2.2 Global aggregators
Global aggregators 对所有搜索上下文的文档定义了一个单bucket, 该文档是有搜索的索引和文档类型决定的,而不受查询条件影响。
Global aggregators 只能放在最上层聚合中,若将其放在另外一个bucket聚合中就有些不合理。
案例:分别计算所有订单的平均交易额和elyssa订单的平均交易额
1)query 过滤出elyssa
2)aggs ->avg 获取elyssa的订单平均金额
3)aggs ->global{},aggs->avg 计算全局订单平均金额
GET kibana_sample_data_ecommerce/_search?size=0
{
"query": {
"term": {
"user": {
"value": "elyssa"
}
}
},
"aggs": {
"all_avg_order_money": {
"global": {},
"aggs": {
"avg_money":{
"avg": {
"field": "taxful_total_price"
}
}
}
},
"elyssa_avg_order_money":{
"avg": {
"field": "taxful_total_price"
}
}
}
}
注:global必须放在最外层,golbal这一层加个aggs的avg就可以继续计算全局数据的平均值了
输出:
{
...
"aggregations" : {
"elyssa_avg_order_money" : {
"value" : 88.46978268678161
},
"all_avg_order_money" : {
"doc_count" : 14025,
"avg_money" : {
"value" : 75.05542864304813
}
}
}
}
2.3 Histogram Aggregation
Histogram Aggregation 属于多bucket类型的聚合,它可以对数值字段按照固定的间隔聚合, 其bucket_key 计算方法如下:
bucket_key = Math.floor((value - offset) / interval) * interval + offset
kibana_sample_data_ecommerce/_search?size=0
{
"aggs": {
"range_price": {
"histogram": {
"field": "products.price",
"interval": 50,
"min_doc_count": 1,
"keyed": true,
"extended_bounds": {
"min": 0,
"max": 500
}
}
}
}
}
min_doc_count 默认为0,即某个范围内bucket为空也会生成一个bucket;设置为1后,至少匹配到1个文档后才产生一个bucket;
keyed 默认为false,数据都保存在buckets的数组中;设置为true后,数据存在在对应的buckets的json对象中,每个bucket的key的值即为上述方法计算的buckek_key;
extended_bounds 默认不存在,设置后值会匹配min-max之间的数据;
此外还可以设置missing的数值;;
2.4 Date Histogram Aggregation
Date Histogram Aggregation属于多bucket类型的聚合,它可以对时间字段按照固定的间隔聚合。
GET kibana_sample_data_ecommerce/_search?size=0
{
"aggs": {
"range_order_time": {
"date_histogram": {
"field": "order_date",
"calendar_interval": "1q"
}
}
}
}
间隔有3种,分别为calendar_interval,fixed_interval,interval
calendar_interval: 与日历相关的间隔,因此按照月份的话会存在不同月份天数不同,其单位只能为单倍的时间单位,立即ms,s,m,d,M,q,y等;
fixed_interval: 做为对照,通常是多倍的时间单位,如1m,2h,3d等,由于是固定的间隔,而月年等单位天数不是固定的,因此不可以使用,即fixed模式最大的单位为d;
interval: 容易造成歧义,后续将会被弃用,此处不解释;
2.5 Date Range Aggregation
该聚合是专用于时间字段的范围聚合,每个聚合内包含from值所在的数据,不包含to值所在的数据。
GET kibana_sample_data_ecommerce/_search?size=0
{
"aggs": {
"range_order_time": {
"date_range": {
"field": "order_date",
"format": "dd-MM-yyy",
"time_zone": "CET",
"ranges": [
{"from": "now-2d","to": "now-1d"},
{"to":"now-2d"},
{"from": "now"}
]
}
}
}
}
该聚合也可以使用如下属性:
keyed,
missing
2.6 Range Aggregation
与date_range 相对,该聚合对数值类型字段按照范围就行聚合,且可以接受脚本参数。
GET kibana_sample_data_ecommerce/_search?size=0
{
"aggs": {
"price_ranges": {
"range": {
"field": "taxful_total_price",
"ranges": [
{"from": "100","to":"200"},
{"to":"100"},
{"from": "200"}
]
}
}
}
}
也可以将filed改为脚本参数:
"script": {
"lang": "painless",
"source": "doc.taxful_total_price.value"
},
待补充
3 注意事项
to add
4 说明
测试环境:es 7.2.1
7.2/search-aggregations
es 权威指南:aggs-high-level