0
点赞
收藏
分享

微信扫一扫

es笔记六之聚合操作之指标聚合

本文首发于公众号:Hunter后端 原文链接:es笔记六之聚合操作之指标聚合

聚合操作,在 es 中的聚合可以分为大概四种聚合:

  • bucketing(桶聚合)
  • mertic(指标聚合)
  • matrix(矩阵聚合)
  • pipeline(管道聚合)

bucket 类似于分类分组,按照某个 key 将符合条件的数据都放到该类别的组中

mertic 计算一组文档的相关值,比如最大,最小值

matrix 根据多个 key 从文档中提取值生成矩阵,这个操作不支持脚本(script)

pipeline 将其他聚合的结果再次聚合输出

聚合是支持套娃(嵌套)操作的,你可以在聚合的结果上接着进行聚合操作,es 是不限制聚合的深度的。

本篇笔记目录如下:

  1. 指标聚合的基本结构
  2. 平均值聚合
  3. 去重统计
  4. 聚合统计汇总
  5. 最大值、最小值聚合
  6. 百分位统计
  7. 百分位排名
  8. 字符串统计聚合
  9. sum 统计总和操作
  10. count 统计总数操作
  11. top hit 操作

1、指标聚合的基本结构

指标聚合操作的基本结构大致如下:

GET /bank/_search
{
size: 0,
aggs: {
aggregation_
name: {
agg_name: {
field: field_name
}
}
}
}

其中,aggregation_name 为聚合返回结果的名称,由我们自己定义,agg_name 为聚合的参数,比如最大值最小值,平均值等,这个我们在下面介绍。

指标聚合

指标聚合是从文档中提取字段值出来进行计算得出结果,比如最大最小平均值等。

接下来将详细介绍各种指标聚合操作。

2、平均值聚合

GET /bank/_search
{
size: 0,
aggs: {
avg_
balance: {
avg: {
field: balance
}
}
}
}

其中,最外层的 aggs 表示是聚合操作,avg_balance 是聚合的名称,avg 则表示是平均值聚合,里面的 field 表示聚合的字段是 balance 字段

在这里,如果不添加 size=0,除了会返回我们的聚合结果,还会返回聚合的源数据。

这个操作我们返回的结果如下:

{
took : 1,
timed_out : false,
_shards : {
total : 1,
successful : 1,
skipped : 0,
failed : 0
},
hits : {
total : {
value : 1000,
relation : eq
},
max_score : null,
hits : [ ]
},
aggregations : {
avg_balance : {
value : 25714.837
}
}
}

我们聚合的结果在 aggregations 这个 key 下。

脚本执行

脚本执行的方式如下:

GET /bank/_search
{
size: 0,
aggs: {
avg_balance: {
avg: {
script: {source: doc.balance.value}
}
}
}
}

对结果处理

假设,我们需要对这个平均值结果进行处理,比如我们计算出来的这个值是 2000,我们想要对这个值进行修正,比如乘以 1.2。

当然,这个乘的操作我们可以获取数据之后在系统里进行操作,如果是直接在 es 的处理中,我们可以如下实现:

GET /bank/_search
{
size: 0,
aggs: {
avg_corrected_balance: {
avg: {
field: balance,
script: {
lang: painless,
source: _value * params.correction,
params: {correction: 1.2}

}
}
},
avg_balance: {
avg: {
script: {source: doc.balance.value}
}
}
}
}

在上面的语句中,我们新增了一个 params 字段,定义了一个 correction 的值,然后返回的结果乘以了这个值。

在这里,我额外加了一个 avg_balance,是直接用的平均值聚合结果,主要是用来对比这两个结果。

缺失值补充

有一些情况,我们在导入数据的时候,可能某条数据的某个字段是没有值的,默认情况下他们是会被忽略的,不计入计算的,但是如果想要为其加一个默认值也是可以实现的,这里我们用到 missing 这个参数来定义:

GET /bank/_search
{
size: 0,
aggs: {
avg_
balance: {
avg: {
field: balance,
missing: 0
}
}
}
}

3、去重统计

是对某个字段进行去重后统计总数,操作如下:

GET /bank/_search
{
size: 0,
aggs: {
age_
count: {
cardinality: {
field: age
}
}
}
}

需要注意的是,这个统计对于 text 字段属性是不生效的

4、聚合统计汇总

有一个聚合统计汇总的参数 stats,可以将一般的聚合值进行汇总后返回,比如总数,最大值,最小值等,使用如下:

GET /bank/_search
{
size: 0,
aggs: {
age_
stats: {
stats: {
field: age
}
}
}
}

可以看到返回的值如下:

{
...
aggregations : {
age_stats : {
count : 1000,
min : 20.0,
max : 40.0,
avg : 30.171,
sum : 30171.0
}
}
}

如果还想获得方差,标准差等数据,可以使用这个参数的扩展版 extended_stats,替换聚合的参数 stats 即可。

5、最大值、最小值聚合

最大值最小值的关键字是 max 和 min,使用示例如下:

GET /bank/_search
{
size: 0,
aggs: {
max_age: {
max: {field: age}
},
min_age: {
min: {field: age}
}
}
}

使用脚本的方式来实现:

GET /bank/_search
{
size: 0,
aggs: {
max_age: {
max: {script: {source: doc.age.value}}
}
}
}

6、百分位统计

使用 es 进行百分位的统计,用到的关键字是 percentiles

使用示例如下:

GET /bank/_search
{
size: 0,
aggs: {
age_
percentiles: {
percentiles: {
field: age
}
}
}
}

会输出 [1, 5, 25, 75, 95, 99] 的统计数:

{
...
aggregations : {
age_percentiles : {
values : {
1.0 : 20.0,
5.0 : 21.0,
25.0 : 25.0,
50.0 : 30.8,
75.0 : 35.0,
95.0 : 39.0,
99.0 : 40.0
}
}
}
}

我们也可以指定统计的百分位的数列表,比如我们只想知道 [75, 98, 99, 99.9] 的数据:

GET /bank/_search
{
size: 0,
aggs: {
age_percentiles: {
percentiles: {
field: age,
percents: [75, 98, 99, 99.9]
}
}
}
}

我们直接使用是返回的百分位-数据的格式,我们也可以使用 {'key': xx, 'value': xx} 来返回一个列表,加上一个参数 keyed=false 即可

GET /bank/_search
{
size: 0,
aggs: {
age_percentiles: {
percentiles: {
field: age,
keyed: false
}
}
}
}

返回的结果示例如下:

    age_percentiles : {
values : [
...
{
key : 75.0,
value : 35.0
},
{
key : 95.0,
value : 39.0
},
{
key : 99.0,
value : 40.0
}
]
}
}
}

7、百分位排名

这个是和前面的百分位统计相反的操作。

前面是根据百分位获取该百分位值,这个参数的作用是根据数据获取在系统中的百分位,使用示例如下:

GET /bank/_search
{
size: 0,
aggs: {
age_ranks: {
percentile_ranks: {
field: age,
values: [
30,
35,
40
]
}
}
}
}

8、字符串统计聚合

对于字符串类型的数据,有一个专门的参数来获取相应的聚合统计值,为 string_stats

对 lastname 字段的统计示例如下:

GET /bank/_search
{
size: 0,
aggs: {
last_
name_stats: {
string_
stats: {field: lastname.keyword}
}
}
}

需要注意,如果我们需要进行统计的字段如果是 text 字段,那么就需要加上 .keyword 来进行统计,如果是字段属性是 keyword,就不需要这样处理。

经过统计返回的数据如下:

  ... 
aggregations : {
last_name_stats : {
count : 1000,
min_length : 2,
max_length : 11,
avg_length : 6.122,
entropy : 4.726472133462717
}
}
}

以上信息包括数据总数,lastname 字段最长和最短长度,平均长度和熵值

9、sum 统计总和操作

比如我们需要对 bank 这个数据库的 age 字段进行 sum 的操作,可以如下操作:

GET /bank/_search
{
size: 0,
aggs: {
age_
sum: {
sum: {field: age}
}
}
}

在前面的每一个聚合操作里,都可以进行 query 的条件筛选,比如获取 age=21 的数据的 sum 值:

GET /bank/_search
{
size: 0,
query: {match: {age: 21}},
aggs: {
age_sum: {
sum: {field: age}
}
}
}

10、count 统计总数操作

count 是统计总数,使用示例如下:

GET /bank/_search
{
size: 0,
aggs: {
age_
count: {
value_count: {
field: age
}
}
}
}

11、top hit 操作

top hit 操作是根据条件返回符合条件的前几条数据,通过 size 控制返回的数量。

我们先来看下下面的这个操作:

GET /bank/_search
{
size: 0,
aggs: {
top_
ages: {
terms: {
field: age,
size: 30
}
}
}
}

这个操作其实就是一个桶聚合,它会在下一篇笔记中介绍,这里我们直接用一下,它返回字段为 age,以及它在文档中的数量:

  ...
aggregations : {
top_ages : {
doc_count_error_upper_bound : 0,
sum_other_doc_count : 0,
buckets : [
{
key : 31,
doc_count : 61
},
{
key : 39,
doc_count : 60
},
{
key : 26,
doc_count : 59
},
...

top_hits 的操作是在第一个 aggs 聚合操作条件下,进行再次聚合。

比如我们想要获取各个 age 的数据中,按照 balance 字段进行倒序排序的前三个,我们可以如下操作:

GET /bank/_search
{
size: 0,
aggs: {
top_ages: {
terms: {
field: age,
size: 30
},
aggs: {
top_balance_hits: {
top_hits: {
size: 3,
sort: [{balance: {order: desc}}]
}
}
}
}
}
}

然后在第一次聚合返回的结果中,就会多一个 top_balance_hits 字段,也就是我们在查询操作中指定的,其下会有三条按照 balance 字段倒序返回的数据:

  ...
aggregations : {
top_ages : {
doc_count_error_upper_bound : 0,
sum_other_doc_count : 0,
buckets : [
{
key : 31,
doc_count : 61,
top_balance_hits : {
hits : {
total : {
value : 61,
relation : eq
},
max_score : null,
hits : [
...
]
},
{
key : 39,
doc_count : 60,
...
},
{
key : 26,
doc_count : 59,
...
},
...
举报

相关推荐

0 条评论