Elasticsearch 聚合
Elasticsearch 聚合
聚合将数据汇总为指标、统计数据或其他分析。
Elasticsearch 将聚合分为三类:
类型 | 说明 |
---|---|
Metric(指标聚合) | 根据字段值进行统计计算 |
Bucket(桶聚合) | 根据字段值、范围或其他条件进行分组 |
Pipeline(管道聚合) | 根据其他聚合结果进行聚合 |
聚合的用法
所有的聚合,无论它们是什么类型,都遵从以下的规则。
- 通过 JSON 来定义聚合计算,使用
aggregations
或aggs
来标记聚合计算。需要给每个聚合起一个名字,指定它的类型以及和该类型相关的选项。 - 它们运行在查询的结果之上。和查询不匹配的文档不会计算在内,除非你使用 global 聚集将不匹配的文档囊括其中。
- 可以进一步过滤查询的结果,而不影响聚集。
以下是聚合的基本结构:
1 | "aggregations" : { <!-- 最外层的聚合键,也可以缩写为 aggs --> |
- 在最上层有一个 aggregations 的键,可以缩写为 aggs。
- 在下面一层,需要为聚合指定一个名字。可以在请求的返回中看到这个名字。在同一个请求中使用多个聚合时,这一点非常有用,它让你可以很容易地理解每组结果的含义。
- 最后,必须要指定聚合的类型。
关于聚合分析的值来源,可以取字段的值,也可以是脚本计算的结果。
但是用脚本计算的结果时,需要注意脚本的性能和安全性;尽管多数聚集类型允许使用脚本,但是脚本使得聚集变得缓慢,因为脚本必须在每篇文档上运行。为了避免脚本的运行,可以在索引阶段进行计算。
此外,脚本也可以被人可能利用进行恶意代码攻击,尽量使用沙盒(sandbox)内的脚本语言。
::: details 【示例】根据 my-field 字段进行 terms 聚合计算
1 | GET /my-index-000001/_search |
响应结果:
1 | { |
:::
::: details 用于测试的数据
为 /employees
索引添加测试数据:
1 | DELETE /employees |
:::
限定数据范围
ES 聚合分析的默认作用范围是 query
的查询结果集。
同时 ES 还支持以下方式改变聚合的作用范围:
filter
- 只对当前子聚合语句生效post_filter
- 对聚合分析后的文档进行再次过滤global
- 无视 query,对全部文档进行统计
::: details 【示例】使用 query 限定聚合数据的范围
1 | POST /employees/_search |
:::
::: details 【示例】使用 filter 限定聚合数据的范围
1 | POST /employees/_search |
:::
控制返回聚合结果
::: details 【示例】仅返回聚合结果
使用 field
限定聚合返回的展示字段:
1 | POST /employees/_search |
默认情况下,包含聚合的搜索会同时返回搜索命中和聚合结果。要仅返回聚合结果,请将 size
设置为 0
:
1 | POST /employees/_search |
:::
聚合结果排序
::: details 【示例】聚合结果排序
指定 order
,按照 _count
和 _key
进行排序。
1 | POST /employees/_search |
:::
运行多个聚合
::: details 【示例】运行多个聚合
可以在同一请求中指定多个聚合:
1 | POST /employees/_search |
:::
运行子聚合
::: details 【示例】运行子聚合
Bucket 聚合支持 Bucket 或 Metric 子聚合。例如,具有 avg 子聚合的 terms 聚合会计算每个桶中文档的平均值。嵌套子聚合没有级别或深度限制。
1 | POST /employees/_search |
响应将子聚合结果嵌套在其父聚合下:
1 | { |
:::
Metric(指标聚合)
指标聚合主要从不同文档的分组中提取统计数据,或者,从来自其他聚合的文档桶来提取统计数据。
这些统计数据通常来自数值型字段,如最小或者平均价格。用户可以单独获取每项统计数据,或者也可以使用 stats 聚合来同时获取它们。更高级的统计数据,如平方和或者是标准差,可以通过 extended stats 聚合来获取。
ES 支持的指标聚合类型:
类型 | 说明 |
---|---|
avg | 平均值聚合 |
boxplot | 箱线图聚合 |
cardinality | 近似计算非重复值 |
extended_stats | 扩展统计聚合 |
geo_bounds | 地理边界聚合 |
geo_centroid | 根据* geo *字段的所有坐标值计算加权质心 |
geo_line_geo_line | 根据地理数据生成可用于线性几何图形展示的数据 |
cartesian_bounds | 笛卡尔积边界聚合 |
cartesian_centroid | 计算所有坐标值加权质心 |
matrix_stats | 矩阵统计聚合 |
max | 最大值聚合 |
median_absolute_deviation | 中位数绝对偏差聚合 |
min | 最小值聚合 |
percentile_ranks | 百分位排名聚合 |
percentiles | 百分位聚合 |
rate | 频率聚合 |
scripted_metric | 脚本化指标聚合 |
stats | 统计聚合 |
string_stats | 字符串统计聚合 |
sum | 求和聚合 |
t_test | 校验聚合 |
top_hits | 热门点击统计 |
top_metrics | 热门指标聚合 |
value_count | 值统计聚合 |
weighted_avg | 加权平均值聚合 |
::: details 【示例】指标聚合示例
Metric 聚合测试:
1 | // Metric 聚合,找到最低的工资 |
:::
Bucket(桶聚合)
桶聚合不会像指标聚合那样计算字段的指标,而是创建文档桶。每个桶都与一个标准(取决于聚合类型)相关联,该标准确定当前上下文中的文档是否“落入”其中。换句话说,桶有效地定义了文档集。除了桶本身之外,桶
聚合还计算并返回“落入”每个桶的文档数。
与指标
聚合相反,桶聚合可以保存子聚合。这些子聚合将针对其 “父” 桶聚合创建的桶进行聚合。
Elasticsearch 中支持的桶聚合类型:
类型 | 说明 |
---|---|
adjacency_matrix | 邻接矩阵聚合 |
auto_interval_date_histogram | 自动间隔日期直方图聚合 |
categorize_text | 对文本进行分类聚合 |
children | 子文档聚合 |
composite | 组合聚合 |
date_histogram | 日期直方图聚合 |
date_range | 日期范围聚合 |
diversified_sampler | 多种采样器聚合 |
filter | 过滤器聚合 |
filters | 多过滤器聚合 |
geo_distance | 地理距离聚合 |
geohash_grid | geohash 网格 |
geohex_grid | geohex 网格 |
geotile_grid | geotile 网格 |
global | 全局聚合 |
histogram | 直方图聚合 |
ip_prefix | IP 前缀聚合 |
ip_range | IP 范围聚合 |
missing | 空值聚合 |
multi_terms | 多词项分组聚合 |
nested | 嵌套聚合 |
parent | 父文档聚合 |
random_sampler | 随机采样器聚合 |
range | 范围聚合 |
rare_terms | 稀有多词项聚合 |
reverse_nested | 反向嵌套聚合 |
sampler | 采样器聚合 |
significant_terms | 重要词项聚合 |
significant_text | 重要文本聚合 |
terms | 词项分组聚合 |
time_series | 时间序列聚合 |
variable_width_histogram | 可变宽度直方图聚合 |
::: details 【示例】terms 聚合查询
默认,ES 不允许对 Text 字段进行 terms 聚合查询
1 | // 对 keword 进行聚合 |
:::
::: details 【示例】更多 Bucket 聚合示例
1 | // 对 job 进行近似去重统计 |
:::
Pipeline(管道聚合)
管道聚合处理从其他聚合而不是文档集生成的输出,从而将信息添加到输出树中。
Pipeline 聚合的分析结果会输出到原结果中,根据位置的不同,分为两类:
- sibling - 结果和现有分析结果同级。例如:max_bucket、min_bucket、avg_bucket、sum_bucket、stats_bucket、extended_stats_bucket、percentiles_bucket。
- parent - 结果内嵌到现有的聚合分析结果中。例如:derivative、cumulative_sum、moving_function。
管道聚合可以通过使用 buckets_path
参数来指示所需指标的路径,从而引用执行计算所需的聚合。管道聚合不能具有子聚合,但根据类型,它可以引用buckets_path
中的另一个管道,从而允许链接管道聚合。
以下为 Elasticsearch 支持的管道聚合类型:
类型 | 说明 |
---|---|
avg_bucket | 平均桶 |
bucket_script | 桶脚本 |
bucket_count_ks_test | 桶数 k-s 测试 |
bucket_correlation | 桶关联 |
bucket_selector | 桶选择器 |
bucket_sort | 桶排序 |
change_point | 更改点 |
cumulative_cardinality | 累积基数 |
cumulative_sum | 累计总和 |
derivative | 导数 |
extended_stats_bucket | 扩展的统计信息桶 |
inference_bucket | 推理桶 |
max_bucket | 最大桶 |
min_bucket | 最小桶 |
moving_function | 移动功能 |
moving_percentiles | 移动百分位数 |
normalize | 正常化 |
percentiles_bucket | 百分位数桶 |
serial_differencing | 序列差分 |
stats_bucket | 统计桶 |
sum_bucket | 总和桶 |
::: details 【示例】Pipeline 聚合示例
1 | // 平均工资最低的工作类型 |
:::
聚合的执行流程
ES 在进行聚合分析时,协调节点会在每个分片的主分片、副分片中选一个,然后在不同分片上分别进行聚合计算,然后将每个分片的聚合结果进行汇总,返回最终结果。
由于,并非基于全量数据进行计算,所以聚合结果并非完全准确。
要解决聚合准确性问题,有两个解决方案:
- 解决方案 1:当数据量不大时,设置 Primary Shard 为 1,这意味着在数据全集上进行聚合。
- 解决方案 2:设置
shard_size
参数,将计算数据范围变大,进而使得 ES 的整体性能变低,精准度变高。shard_size 值的默认值是size * 1.5 + 10
。