ES聚合命令
ES中的聚合查询类似于SQL的分组查询,主要用于统计分析场景。
查询流程为按需分组和桶内聚合
查询流程 | 流程功能 | sql语句 |
按需分桶 | 对查询的数据根据需求进行初步筛选、并根据不同条件份桶,比如学生按专业分班的过程 | group by |
桶内聚合 | 对分桶的数据进行分析统计,比如统计一个班内学生的总数、平均成绩等 | avg、sum、count |
其中es的概念
相关概念 | 概念解释 |
桶bucket | 满足特定条件的文档的集合 |
桶聚合 | 创建文档存储桶,把具有相同标准的数据分桶,并统计每个桶的文档数量 |
指标聚合 | 指标指的是对文档进行统计的计算方式,如sum、avg、count、max等 |
聚合查询基本命令
{
"aggregations" : { # 指明以下为聚合查询语句,可以简写为aggs
"<aggregation_name>" : { # 聚合计算的名字(随意命名)便于之后通过这个名字来获取想要的计算结果
"<aggregation_type>" : { # 指定聚合类型,桶聚合和指标聚合
<aggregation_body> # 聚合类型的参数,选择不同的聚合类型,有不同的参数
}
[,"aggregations" : { [<sub_aggregation>]+ } ]? # 嵌套聚合查询,支持多层嵌套
}
[,"<aggregation_name_2>" : { ... } ]* # 其他聚合查询的名称
}
}
假设存在一个索引school
,里边存储了所有的学生信息的文档,每个人都包含了字段class
,希望通过字段class
进行分组。
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果,不返回普通query查询结果。
"aggs" : { # 聚合查询的简写
"class_num" : { # 给聚合查询取个名字,叫class_num
"terms" : { # 聚合类型为桶聚合的terms,类似SQL的group by的作用,相同字段值的文档分为一组。
"field" : "class" # terms聚合类型的参数,这里需要设置分组的字段为class,根据color分组
}
}
}
}
没有明确指定指标聚合函数默认使用Count聚合指标统计文档总数, 统计每一个class的学生人数,类似于sql语句:
select count(class) from school group by class
查询结果如下
{
...
"hits": { # size=0,query查询结果不展示
"hits": []
},
"aggregations": { # 聚合查询结果
"class_num": { # class_num聚合查询的结果
"buckets": [ # 桶聚合会返回buckets数组,代表分桶的统计情况,可以看到每个班的人数情况
{
"key": "Class_1",
"doc_count": 36 # 一班有36个人
},
{
"key": " Class_2",
"doc_count": 42 # 二班有42个人
},
{
"key": "Class_3",
"doc_count": 37 # 三班有37个人
}
]
}
}
}
桶聚合
桶聚合,目的就是数据分组,先将数据按指定的条件分成多个组,然后对每一个组进行统计。每一个组就叫做桶(bucket)。桶聚合的作用跟SQL的group by的作用是一样的,但ES支持更加强大的数据分组能力。ES常用的桶聚合方法有:
聚合方法 | 方法解释 |
Terms聚合 | 类似SQL的group by,根据字段唯一值分组 |
Histogram聚合 | 根据数值间隔: 按100间隔分组产生0、100、200、300组 |
Date histogram聚合 | 根据时间间隔:按月、天、小时分组 |
Range聚合 | 按数值范围:比如分成 0-150、150-20、200-500三组 |
Terms聚合
terms聚合的作用跟SQL中group by作用一样,都是根据字段唯一值对数据进行分组(分桶),字段值相等的文档都分到同一个桶内
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"class_bucket": { # 聚合查询的名字
"terms": { # 聚合类型为:terms
"field": "class" # 根据class字段值分桶
}
}
}
}
相关sql语句
select class, count(*) from order group by class
查询结果如下
{
...
"aggregations" : {
"class_bucket" : { # 聚合查询名字
"buckets" : [ # 桶聚合结果,下面返回各个桶的聚合结果
{
"key" : "Class_1", # key分桶的标识,在terms聚合中,代表的就是分桶的字段值
"doc_count" : 36 # 默认的指标聚合是统计桶内文档总数
},
{
"key" : "Class_2",
"doc_count" : 42
},
{
"key" : "Class_3",
"doc_count" : 37
}
]
}
}
}
Histogram聚合
histogram(直方图)聚合,主要根据数值间隔分组,使用histogram聚合分桶统计结果,通常用在绘制条形图报表
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"histogram_grade": { # 聚合查询的名字
"histogram": { # 聚合类型为:histogram
"field": "grade" # 根据price字段分桶
"interval": 50 # 分桶的间隔为50,意思就是grade字段值按50间隔分组
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"histogram_grade" : { # 聚合查询名字
"buckets": [ # 分桶结果
{
"key": 0.0, # 桶的标识,histogram分桶,这里通常是分组的间隔值,从0开始
"doc_count": 0 # 默认按Value Count指标聚合,统计桶内文档总数
},
{
"key": 50.0,
"doc_count": 115
}
]
}
}
}
Date histogram聚合
类似histogram聚合,但Date histogram可以很好的处理时间类型字段,主要用于根据时间、日期分桶的场景
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"data_of_birth": { # 聚合查询的名字
"date_histogram": { # 聚合类型为:date_histogram
"field": "date" # 根据date字段分桶
"calendar_interval" : "year", # 分组间隔:month代表每月、支持minute(每分钟)、hour(每小时)、day(每天)、week(每周)、year(每年)
"format" : "yyyy-MM-dd" # 设置返回结果中桶key的时间格式
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"data_of_birth": { # 聚合查询名字
"buckets": [ # 桶聚合结果
{
"key_as_string": "2005-01-01", # 每个桶key的字符串标识,格式由format指定
"key": 1104537600000, # key的具体字段值,13位时间戳
"doc_count": 3 # 默认按Value Count指标聚合,统计桶内文档总数
},
{
"key_as_string": "2006-01-01",
"key": 1136073600000,
"doc_count": 2
},
{
"key_as_string": "2007-01-01",
"key": 1167609600000,
"doc_count": 2
},
...
]
}
}
}
Range聚合
自己设计范围,按数值范围分桶
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"range_grade": { # 聚合查询的名字
"range": { # 聚合类型为:range
"field": "grade" # 根据price字段分桶
"ranges": [ # 配置范围
{"key" : "failing", "to": 60.0}, # grade <= 60的文档归类到failing桶
{"key" : "good", "from": 60.0, "to": 80.0}, # 60<grade<80的文档归类到good桶
{"key" : "excellent", "from": 80.0} # grade>80的文档归类到excellent桶
]
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"range_grade" : { # 聚合查询名字
"buckets": [ # 桶聚合结果
{
"key": "failing", # 桶名称
"to": 60.0, # 结束值
"doc_count": 42 # 默认按Value Count指标聚合,统计桶内文档总数
},
{
"key": "good",
"from": 60.0, # 起始值
"to": 80.0, # 结束值
"doc_count": 50
},
{
"key": "excellent",
"from": 80.0,
"doc_count": 23
}
]
}
}
}
指标聚合
指标聚合,类似sql的统计函数,指标聚合可以单独使用,也可以跟桶聚合一起用。常用的统计函数有:
指标名称 | 值聚合Value Count | 基数聚合Cardinality | Avg | Sum | Max | Min |
指标功能 | 统计总数 | 统计不重复的数据总数 | 求平均值 | 求和 | 求最大值 | 求最小值 |
Value Count
值聚合,主要用于统计文档总数,类似SQL的count函数。
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"age_count": { # 聚合查询的名字
"value_count": { # 聚合类型为:value_count
"field": "age" # 计算age这个字段值的总数
}
}
}
}
相关sql语句
select count(age) from school
查询结果如下
{
...
"aggregations": {
"age_count": { # 聚合查询的名字
"value": 115 # 统计结果,假设学生的年龄均在12-18之间,没有去重所以结果等于学生总数
}
}
}
Cardinality
基数聚合,也是用于统计文档的总数,跟Value Count的区别是,基数聚合会去重,不会统计重复的值,类似SQL的count(DISTINCT 字段)用法
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"age_count": { # 聚合查询的名字
"cardinality": { # 聚合类型为:cardinality
"field": "age" # 计算age这个字段值的总数
}
}
}
}
相关sql语句
select count(DISTINCT age) from school
查询结果如下
{
...
"aggregations": {
"types_count": { # 聚合查询的名字
"value": 7 # 统计结果,假设学生的年龄均在12-18岁之间,去重所以结果等于不同年龄数值
}
}
}
Avg
计算字段值的平均值
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"avg_grade": { # 聚合查询的名字,学生成绩平均
"avg": { # 聚合类型为:avg
"field": "grade" # 计算grade这个字段值的平均值
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"avg_grade": { # 聚合查询的名字
"value": 80.0 # 统计结果,学生成绩的平均值
}
}
}
Sum
计算字段值的总和
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"sum_grade": { # 聚合查询的名字,学生成绩总和
"sum": { # 聚合类型为:sum
"field": "grade" # 计算grade这个字段值的总和
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"sum_grade": { # 聚合查询的名字
"value": 9200 # 统计结果,(avg_grade = 80) * (age_count = 115) = (sum_grade = 9200)
}
}
}
Max
获得字段的最大值
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"max_grade": { # 聚合查询的名字,学生的最好成绩
"max": { # 聚合类型为:max
"field": "grade" # 计算grade这个字段值的最大值
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"max_grade": { # 聚合查询的名字
"value": 100 # 统计结果,学生最高分为100
}
}
}
Min
获得字段的最小值
# 聚合命令
GET /school/_search
{
"size" : 0, # 设置size=0的意思就是,仅返回聚合查询结果
"aggs": { # aggs为聚合查询结果
"min_grade": { # 聚合查询的名字,学生最低成绩
"min": { # 聚合类型为:min
"field": "grade" # 计算grade这个字段值的最小值
}
}
}
}
# 查询结果如下
{
...
"aggregations": {
"min_grade": { # 聚合查询的名字
"value": 60 # 统计结果,学生最低分为60
}
}
}