elk笔记16--聚合分析
Posted 昕光xg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了elk笔记16--聚合分析相关的知识,希望对你有一定的参考价值。
elk笔记16--聚合分析
- 2.3.1 Avg Bucket Aggregation
- 2.3.2 Max Bucket Aggregation
- 2.3.3 Min Bucket Aggregation
- 2.3.4 Sum Bucket Aggregation
- 2.3.5 待补充
- 3 常用案例
- 3.1 统计购物次数前n的用户
- 3.2 分别统计每个月中单次消费最高的前2位用户
- 3.3 分别统计每个用户周一-周日的购物次数
- 3.4 统计不同消费额范围的购物次数(100为单位)
- 3.5 按月统计指定时间范围内每月订单数量
- 3.6 统计用户 elyssa 周一-周日的购物次数
- 3.7 同时获取用户 elyssa 的平均订单价格和所有用户的平均订单价格
1 聚合概念
在es中,聚合框架基于一个搜索查询为我们提供聚合后的数据。es基于一系列简单的聚合模块,并加以组合就可以构建出复杂的数据统计。
聚合可以看作一个unit-of-work对特定文档集构建的可分析的信息,文档集合通常又一次执行的上下文构成的,例如最上层聚合的query|filters就可以决定要聚合的文档集。
es 中有多种类型的聚合,每种都有其聚合目的和输出结果,为了方便理解聚合,es将其分为四类:Bucketing,Metric,Matrix,Pipeline。
下文将会依次挑选一些加以分析,案例数据源为kibana中自带的kibana_sample_data_ecommerce索引。
桶和指标是es聚合中2个非常重要的概念:
bucket 指的是满足特定条件的一组文档的集合,例如一个班级整体可以为一个bucket,班内又可以继续以男女分为2个bucket;
metric 对一个bucket执行的某种聚合分析的操作,比如说求平均值、最大值、最小值等;
以sql查询为例: select count(*) from access_log group by user_id;
group by user_id 将数据划分为多个bucket,count(*) 对数据进行统计,桶在概念上类似于 SQL 的分组(GROUP BY),而指标则类似于 COUNT() 、 SUM() 、 MAX() 等统计方法。
2 聚合类型
2.1 Bucketing
在桶聚合中,一组聚合构成了多个桶,每个桶与一个关键字、一个文档规则相关联。当一个聚合被执行后,所有的桶规则都会对每一文档进行评估,如果匹配到了某个规则,该文档就会被放到对应桶中。聚合完成后,将会得到一组桶,每个桶里面都会有属于它的文档集。
Bucket 聚合并不会想指标聚合一样在字段上计算属性,它只创建很多文档的桶。每个bucket与一个规则相关联,该规则决定了一个文档是否在某个桶中。换句话说,buckets很高效地定义了文档集合。除了buckets自己外,bucket聚合也计算并返回bucket的文档数量。
与指标聚合相反,bucket聚合可以包含子聚合。子聚合根据其父bucket聚合的bucket文档,可以进一步聚合出一系列文档集合。
es 中有很多不同类型的bucket聚合,每一个都有不同的桶策略。一些定义了单个bucket,一些定义了固定数量的多buckets,还有一些bucket聚合在聚合过程中动态创建buckets。
需要注意的是:es中单次返回的最大桶数量默认为10000,该值可以通过集群参数search.max_buckets来设置,如果返回的桶数量超过该值就会报错。
es7.2 中包含了24种 bucket 类型的聚合,下面对 Terms 类型聚合进行介绍,更多其它类型 bucket 聚合将补充在 elk笔记16–aggs-Bucket Aggregations 中。
2.1.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
]
2.2 Metric
指标类的聚合,在es中主要用于追踪和计算一个文档集的属性。
在指标聚合家族中,聚合可以对一些指标进行计算,这些指标基于从已有的聚合文档中提取出来的值,这些值一把是从文档的字段提取的,当然也可以通过脚本产生。
数值类型的指标聚合是一类特有的指标聚合,它输出一些数字类型的值。其中一类聚合输出单个数值指标,被称为单值数值指标聚合,例如求平均数avg;另外一类输出多个数值指标,被称作多只数值指标聚合。当这些聚合充当某些桶聚合的直接子聚合时(一些桶聚合根据桶中的数值属性,可以使我们对返回桶进行排序),单值和多值数字指标聚合之间的区别将发挥作用。
es7.2 中包含了16种 Metric 类型的聚合,下面对 Terms 类型聚合进行介绍,更多其它类型 bucket 聚合将补充在 elk笔记16–aggs-Metrics Aggregations 中。
2.2.1 Avg Aggregation
计算指定字段的平均值
GET kibana_sample_data_ecommerce/_search?size=0
"aggs" :
"avg_taxful_total_price" :
"avg" :
"field" : "taxful_total_price"
结果:
...
"aggregations" :
"avg_taxful_total_price" :
"value" : 1052652.38671875
使用脚本获取指定字段的值:
avg内部的field改为script,source为doc.字段名称.value
GET kibana_sample_data_ecommerce/_search?size=0
"aggs" :
"avg_taxful_total_price" :
"avg" :
"script":
"source": "doc.taxful_total_price.value"
2.3 Pipeline
Pipeline聚合主要用于对其它聚合的结果和相关属性进行聚合汇总,可以在输出结果中添加一些信息,而不是对文档集进行操作。
es 中有很多不同pipeline聚合,每一类都会从聚合结果中计算不同的信息,当前可以把它们分为2类:Parent类型pipeline聚合,Sibling类型pipeline聚合。
Parent 类型的聚合能够随着父聚合的输出而提供相关聚合信息,它能够计算新的buckets或者新的聚合,并将其添加到已经存在的buckets中。
Pipeline 类型的聚合能虽则兄弟聚合的输出而提供相关的聚合谢谢,它能够计算新的聚合,当时该聚合只能和sibling聚合同级。
通过buckets_path参数(该参数指出来所需指标的路径),管道聚合可以引用它们需要的聚合来执行一些计算任。定义这些路径的语法可以在下文中的buckets_path语法中找到。
管道聚合不能有子聚合,但是根据其类型,它可以引用buckets_path中的另一个管道,从而允许管道聚合被链接。例如,可以将两个导数串在一起来计算二阶导数(即导数的导数)。
因为管道聚合只添加信息到输出结果中,所以在链接管道聚合时,每个管道聚合的输出将包含在最终输出中。
案例:计算最大月销售额
1)date_histogram 按月分桶
2)计算每个桶的总销售额度
3)通过max_monthly_sales pipeline的max_bucket 来计算最大月销售额
GET kibana_sample_data_ecommerce/_search?size=0
"aggs":
"group_by_month":
"date_histogram":
"field": "order_date",
"calendar_interval": "month"
,
"aggs":
"sum_total_money":
"sum":
"field": "taxful_total_price"
,
"max_monthly_sales":
"max_bucket":
"buckets_path": "group_by_month>sum_total_money"
结果:
...
"aggregations" :
"group_by_month" :
"buckets" : [
···
"key_as_string" : "2020-09-01T00:00:00.000Z",
"key" : 1598918400000,
"doc_count" : 2902,
"sum_total_money" :
"value" : 219656.1328125
]
,
"max_monthly_sales" :
"value" : 286406.5234375,
"keys" : [
"2020-04-01T00:00:00.000Z"
]
2.3.1 Avg Bucket Aggregation
Avg Bucket 属于兄弟类型的管道聚合,其计算兄弟聚合中指定属性的平均值。Avg Bucket中指定的属性必须是数值类型,并且该兄弟聚合必须是多桶类型的聚合。
GET kibana_sample_data_ecommerce/_search?size=0
"aggs":
"group_by_month":
"date_histogram":
"field": "order_date",
"calendar_interval": "month"
,
"aggs":
"sum_month_sales":
"sum":
"field": "taxful_total_price"
,
"avg_month_sales":
"avg_bucket":
"buckets_path": "group_by_month>sum_month_sales"
结果:
...
"aggregations" :
"group_by_month" :
"buckets" : [
...
"key_as_string" : "2020-09-01T00:00:00.000Z",
"key" : 1598918400000,
"doc_count" : 2902,
"sum_month_sales" :
"value" : 219656.1328125
]
,
"avg_month_sales" :
"value" : 175442.064453125
2.3.2 Max Bucket Aggregation
该聚合用于计算指定属性的最大值,属于sibling pipeline aggregation,标志max_bucket,使用方法同Avg Bucket Aggregation。
2.3.3 Min Bucket Aggregation
该聚合用于计算指定属性的最小值,属于sibling pipeline aggregation,标志min_bucket,使用方法同Avg Bucket Aggregation。
2.3.4 Sum Bucket Aggregation
该聚合用于计算指定属性的综合,属于sibling pipeline aggregation,标志sum_bucket,使用方法同Avg Bucket Aggregation。
2.3.5 待补充
2.4 Matrix
矩阵聚合中,有一系列聚合能操作多个字段,并产生一个矩阵结果,这些字段的值是从请求的文档字段只能够提取出来的。与指标和桶聚合不同之处在于这类聚合不支持脚本(es 7.2.x)。
该功能是实验性的功能,并且有可能会在后期版本中被移除。
2.4.1 Matrix Aggregations
matrix_stats 聚合是一个数值聚合,它基于文档集合的字段进行如下统计:
统计类型 | 说明 |
count | Number of per field samples included in the calculation. |
mean | The average value for each field. |
variance | Per field Measurement for how spread out the samples are from the mean. |
skewness | Per field measurement quantifying the asymmetric distribution around the mean. |
kurtosis | Per field measurement quantifying the shape of the distribution. |
covariance | A matrix that quantitatively describes how changes in one field are associated with another. |
correlation | The covariance matrix scaled to a range of -1 to 1, inclusive. Describes the relationship between field distributions. |
下面这个例子通过使用矩阵统计,来描述收入和贫穷之间的关系:
GET /_search
"aggs":
"statistics":
"matrix_stats":
"fields": ["poverty", "income"]
结果:
...
"aggregations":
"statistics":
"doc_count": 50,
"fields": [
"name": "income",
"count": 50,
"mean": 51985.1,
"variance": 7.383377037755103E7,
"skewness": 0.5595114003506483,
"kurtosis": 2.5692365287787124,
"covariance":
"income": 7.383377037755103E7,
"poverty": -21093.65836734694
,
"correlation":
"income": 1.0,
"poverty": -0.8352655256272504
,
"name": "poverty",
"count": 50,
"mean": 12.732000000000001,
"variance": 8.637730612244896,
"skewness": 0.4516049811903419,
"kurtosis": 2.8615929677997767,
"covariance":
"income": -21093.65836734694,
"poverty": 8.637730612244896
,
"correlation":
"income": -0.8352655256272504,
"poverty": 1.0
]
mode 参数(和fields同一层):
对于多字段的矩阵聚合,可以根据需要设置mode字段为 avg, min, max, sum, median.
例如"mode":“median”
missing 参数(和fields同一层):
有些文档可能会缺失某些字段,默认情况下es会忽略掉这样的文档,但missing字段可以定义如何处理缺失的字,一般通过missing参数对指定的字段设置默认的值。
“missing”: “income” : 50000 会使用50000代替缺失的income字段。
Script 参数:
该聚合暂时不支持脚本功能。
3 常用案例
3.1 统计购物次数前n的用户
- 使用terms 指定field为user
- “track_total_hits”: true 确保所有的数据都被匹配到,默认只匹配10000条
- terms中size为1即为top1,默认size为10,如果超出10个需要手动指定
GET kibana_sample_data_ecommerce/_search
"track_total_hits": true,
"size": 0,
"aggs":
"group_by_user":
"terms":
"field": "user",
"size": 1
3.2 分别统计每个月中单次消费最高的前2位用户
- 使用order_date 按照date_histogram来分组,interval位month,
- 在每一个组里面使用top_hits、size:2、sort desc来统计单词消费最高的2个用户,
- 通过_source 和 includes 来选择必要字段
GET kibana_sample_data_ecommerce/_search
"size": 1,
"aggs":
"group_by_order_date":
"date_histogram":
"field": "order_date",
"interval": "month"
,
"aggs":
"top_users":
"top_hits":
"sort": [
"taxful_total_price": "order": "desc"
],
"size": 2,
"_source":
"includes": ["user","taxful_total_price"]
3.3 分别统计每个用户周一-周日的购物次数
POST kibana_sample_data_ecommerce/_search?size=0
"aggs":
"group_by_user":
"terms":
"field": "user"
,
"aggs":
"group_by_week":
"terms":
"field": "day_of_week"
3.4 统计不同消费额范围的购物次数(100为单位)
POST kibana_sample_data_ecommerce/_search?size=0
"aggs":
"group_by_range":
"histogram":
"field": "taxful_total_price",
"interval": 100
,
"aggs":
"sum_price":
"sum":
"field": "taxful_total_price"
3.5 按月统计指定时间范围内每月订单数量
POST kibana_sample_data_ecommerce/_search?size=0
"aggs":
"sales":
"date_histogram":
"field": "order_date",
"interval": "month",
"min_doc_count": 0,
"format": "yyyy-MM-dd",
"extended_bounds":
"min": "2020-03-01",
"max": "2020-08-31"
3.6 统计用户 elyssa 周一-周日的购物次数
POST kibana_sample_data_ecommerce/_search?size=0
"query":
"term":
"user":
"value": "elyssa"
,
"aggs":
"group_by_weekday":
"terms":
"field": "day_of_week"
3.7 同时获取用户 elyssa 的平均订单价格和所有用户的平均订单价格
- 通过query指定elyssa用户
- 通过single_avg_money求elyssa的平均订单价格
- 通过all 中的global: 获取所有数据,使之不受query限制
POST kibana_sample_data_ecommerce/_search?size=0
"query":
"match":
"user": "elyssa"
,
"aggs":
"single_avg_money":
"avg":
"field": "taxful_total_price"
,
"all":
"global": ,
"aggs":
"all_user_avg_money":
"avg":
"field":"taxful_total_price"
4 注意事项
- 最外层使用size:0, 可以过滤掉返回的源数据;
- 使用"track_total_hits": true, 可以避免最多只返回10000条记录的限制;
es 每次查询,默认返回hits最多数量为10000,如果需要返回全部或者大于10000条记录,则可以设置track_total_hits: true;
es 中hits的默认值为10000,但实际数据大于10000的时候,它对所有的数据进行了计算,只不过返回的记录默认最大值为10000,主要为了防止返回数据过大导致性能问题.
实际业务中,如果拉取的数据大于10000条,通常会使用scroll api分批次拉取数据。
5 说明
7.2/search-aggregationses 权威指南:aggs-high-level
以上是关于elk笔记16--聚合分析的主要内容,如果未能解决你的问题,请参考以下文章