聚合分类
聚合,可以简单的理解为数据库操作中的 Distinct
、 Group By
,count
、sum
、Having
等操作,当然,实际的功能还是有差别的。目前 Elasticsearch
中的聚合操作包含以下几种分类:
Bucket
,分桶Metric
,⼀些系列的统计⽅法,包括sum
、max
、min
、avg
、stats
等Matrix
(弃用)Pipeline
,针对 “聚合” 的聚合。基于其他聚合的结果集
之前一直觉得聚合好难,然而真的读完,敲了两遍之后发现也就那样。。。主要还是因为之前看到的都是 bucket_selector
那种复杂操作,没能理解到。
1.Bucket & Metric 聚合分析及嵌套聚合
Aggregation
属于 Search
的 一部分。一般情况下,建议将其 Size
指定为 0
,创建测试索引:
1 | DELETE /employees |
Metric
指标统计,使用 Metric
统计工资的最大值、最小值、平均值示例:
1 | GET employees/_search |
cardinality
基数统计(是近似值!!!),cardinality
聚合基于 HyperLogLog ++ 算法。获取不同的 job
的数量示例:
1 | GET employees/_search |
stats
返回max
、min
、avg
、sum
、count
,extended_stats
会扩展出方差、标准偏差等更专业的统计信息;percentiles
、percentile_ranks
返回百分比(是近似值!!!);top_hits
需作为字聚合与bucket aggs
结合使用;value_count
,统计某字段有值的数量,与cardinality
的区别是不去重,默认忽略空值字段
Terms Aggregation
默认只能对 keyword
类型进行聚合,text
类型的字段需要打开 fielddata
,才能进⾏ Terms Aggregation
(也是近似值!!!)
Bucket Size & Top Hits 使用案例:(先根据工作分组,然后查询每种工作年龄前三的人员)
1 | GET employees/_search |
优化 term
聚合的性能:在新建索引时,为字段 mapping
添加 eager_global_ordinals: true
参数
Range& Histogram Aggs
- 按照数字的范围进行分桶
- 在
range aggs
中,可以自定义key
按照工资范围(Range
)分桶示例:
1 | GET employees/_search |
按照工资的间隔(Histogram
)分桶示例:
1 | #Salary Histogram,工资0到10万,以 5000一个区间进行分桶 |
filter
数据过滤
1 | GET shirts/_search |
2. pipeline聚合
- 指标型:
avg_bucket
、max_bucket
、min_bucket
、sum_bucket
、stats_bucket
、extended_stats_bucket
。 - 百分比:
percentiles_bucket
- 特殊场景,需要在
hostogram
的子聚合下才能执行:derivative
导数聚合,moving_fn
、cumulative_sum
- 特殊操作:
bucket_script
、bucket_selector
min_bucket 和 stats_bucket 实例
按照工作类型分组,找出平均工资最低的工种
1 | # 通过 . 或者 > 符号指定 buckets_path 来进行 pipeline 聚合 |
bucket_script 实例
计算每月的 T
桖销售额占总销售额的百分比
1 | total_sales |
bucket_selector 实例
筛选每月的销售额大于 200
的月份
1 | POST /sales/_search |
与其他的 pipeline
管道聚合一样,bucket_selector
聚合在所有其他同级聚合之后执行。这意味着使用 bucket_selector
聚合来过滤响应中返回的存储桶不会节省运行聚合的执行时间。
bucket_sort
使用子聚合结果:当月的总销售额,降序排序
1 | POST /sales/_search |
3. 聚合的作用范围
ES
聚合分析的默认作⽤范围是query
的查询结果集- 同时
ES
还⽀持以下⽅式改变聚合的作⽤范围:filter
、post_filter
、global
filter 作用范围
1 | GET employees/_search |
post_filter作用范围:
post_filter
用两种应用场景:
- 结果中再次搜索(不推荐,会导致
filter_query
的缓存效果失效) - 聚合后!!!,再过滤返回的
hits
的结果集
1 | # 正常情况下,hits会返回所有的文档,post_filter 将 hits 结果集也限制为大于 35 岁的员工 |
global作用范围
尽管 query
已经限制了范围为 35
岁以上的员工,global_test
通过 global
将作用范围重新改为所有数据。(仅对当前子聚合生效)
1 | GET employees/_search |
4. tips
- 经常使用到的聚合,
Elasticsearch
会缓存下来; - 只返回聚合结果需要设置
size:0
- 可以通过
meta
为聚合结果指定自定义的属性
返回结果将会带上 "meta": { "color": "blue" }
1 | GET /twitter/_search |
あなたが生きる、この世界に