聚合查询
数据聚合即数据的统计分析。常见的聚合方式如下
- 桶聚合:对数据进行分组,相当于sql的group by
- 指标聚合:对数据集使用max() 、min()、avg()、sum()之类的聚合函数,统计最大值、最小值、平均值、总量等指标
主要概念
- 桶(bucket):满足特定条件的文档集合,实质是基于条件来划分文档
- 指标(metric):数据集的一些特征值,比如最大值、最小值、平均值
支持嵌套,桶聚合可以嵌套桶聚合、指标聚合,指标聚合也可以嵌套桶聚合、指标聚合。
对于嵌套的聚合,es只需遍历一次数据,不用多次循环遍历数据,速度快、性能高,但聚合、排序都很耗内存。
聚合可以对index中的所有文档使用,也可以对查询结果使用。
只能对keyword字段使用聚合,不能对text字段使用聚合,如果对text使用聚合,会报错
桶聚合
#对全样数据进行聚合,eg. 统计每个球队的球员(人数)
GET /nba/_search
{
"aggs": {
"team_buckets": { #自定义的聚合名称
"terms": { #按关键字划分。不能换成term、match
"field": "team_name", #指定要聚合的字段。按队名划分桶,一个队一个桶,桶内是该队所有球员的文档,字段的值即桶名
# "include": ["湖人队","公牛队","勇士队"], #指定参与聚合的值,只聚合这些值
# "exclude": ["湖人队"], #指定不参与聚合的值,除了这些值其它都参与聚合
"size": 10, #返回的桶数,默认返回所有的桶
# "order": { #桶的排序方式
# "_count": "desc" #按桶中的文档数降序排列,默认也是按桶中的文档数降序排列
# }
}
}
},
"size": 0 #返回的文档数,默认返回每个桶中的所有文档,设置为0即不返回文档,可提高查询速度。如果不需要获取具体文档,可设置为0
}
#include、exclude可以使用通配符,点号表示任意一个字符,*表示任意多个字符
#按范围划分桶之自定义区间,eg.统计指定年龄区间上的用户数量
GET /user/_search
{
"aggs": {
"age_range": { #自定义的聚合名称
"range": { #按范围划分
"field": "age", #指定字段
"ranges": [ #划分区间
{
"to": 12, # [from,to),只要有一个即可
"key": "12岁以下" #区间别名,类似于sql查询结果集的字段别名,非必需
},
{
"from": 12,
"to": 18,
"key": "12~18岁"
},
{
"from": 18,
"key": "18岁以上"
}
]
}
}
},
"size": 0
}
#按时间日期划分桶
* year(1y)年
* quarter(1q)季度
* month(1M)月份
* week(1w)星期
* day(1d)天
* hour(1h)小时
* minute(1m)分钟
* second(1s)秒
"query": {
"bool": {
"must": [{
"range": {
"@timestamp": {
"gte": 1533556800000,
"lte": 1533806520000
}
}
}]
}
},
// 不显示具体的内容
"size": 0,
// 聚合
"aggs": {
// 自己取的聚合名字
"group_by_grabTime": {
// es提供的时间处理函数
"date_histogram": {
// 需要聚合分组的字段名称, 类型需要为date, 格式没有要求
"field": "@timestamp",
// 按什么时间段聚合, 这里是5分钟, 可用的interval在上面给出
"interval": "5m",
// 设置时区, 这样就相当于东八区的时间
"time_zone":"+08:00",
// 返回值格式化,HH大写,不然不能区分上午、下午
"format": "yyyy-MM-dd HH",
// 为空的话则填充0
"min_doc_count": 0,
// 需要填充0的范围
"extended_bounds": {
"min": 1533556800000,
"max": 1533806520000
}
},
// 聚合
"aggs": {
// 自己取的名称
"group_by_status": {
// es提供
"terms": {
// 聚合字段名
"field": "LowStatusOfPrice"
}
}
}
}
}
#对全样数据进行聚合,eg. 统计每个球队的球员(人数)
GET /nba/_search
{
"aggs": {
"team_buckets": { #自定义的聚合名称
"terms": { #按关键字划分。不能换成term、match
"field": "team_name", #指定要聚合的字段。按队名划分桶,一个队一个桶,桶内是该队所有球员的文档,字段的值即桶名
# "include": ["湖人队","公牛队","勇士队"], #指定参与聚合的值,只聚合这些值
# "exclude": ["湖人队"], #指定不参与聚合的值,除了这些值其它都参与聚合
"size": 10, #返回的桶数,默认返回所有的桶
# "order": { #桶的排序方式
# "_count": "desc" #按桶中的文档数降序排列,默认也是按桶中的文档数降序排列
# }
}
}
},
"size": 0 #返回的文档数,默认返回每个桶中的所有文档,设置为0即不返回文档,可提高查询速度。如果不需要获取具体文档,可设置为0
}
#include、exclude可以使用通配符,点号表示任意一个字符,*表示任意多个字符
#按范围划分桶之自定义区间,eg.统计指定年龄区间上的用户数量
GET /user/_search
{
"aggs": {
"age_range": { #自定义的聚合名称
"range": { #按范围划分
"field": "age", #指定字段
"ranges": [ #划分区间
{
"to": 12, # [from,to),只要有一个即可
"key": "12岁以下" #区间别名,类似于sql查询结果集的字段别名,非必需
},
{
"from": 12,
"to": 18,
"key": "12~18岁"
},
{
"from": 18,
"key": "18岁以上"
}
]
}
}
},
"size": 0
}
#按时间日期划分桶
* year(1y)年
* quarter(1q)季度
* month(1M)月份
* week(1w)星期
* day(1d)天
* hour(1h)小时
* minute(1m)分钟
* second(1s)秒
"query": {
"bool": {
"must": [{
"range": {
"@timestamp": {
"gte": 1533556800000,
"lte": 1533806520000
}
}
}]
}
},
// 不显示具体的内容
"size": 0,
// 聚合
"aggs": {
// 自己取的聚合名字
"group_by_grabTime": {
// es提供的时间处理函数
"date_histogram": {
// 需要聚合分组的字段名称, 类型需要为date, 格式没有要求
"field": "@timestamp",
// 按什么时间段聚合, 这里是5分钟, 可用的interval在上面给出
"interval": "5m",
// 设置时区, 这样就相当于东八区的时间
"time_zone":"+08:00",
// 返回值格式化,HH大写,不然不能区分上午、下午
"format": "yyyy-MM-dd HH",
// 为空的话则填充0
"min_doc_count": 0,
// 需要填充0的范围
"extended_bounds": {
"min": 1533556800000,
"max": 1533806520000
}
},
// 聚合
"aggs": {
// 自己取的名称
"group_by_status": {
// es提供
"terms": {
// 聚合字段名
"field": "LowStatusOfPrice"
}
}
}
}
}
指标聚合
常用的聚合函数
- value_count 该字段有值(不为空)的文档数
- max 最大值
- min 最小值
- avg 平均值
- sum 总量
- stats 同时统计以上5个指标
- extended_stats 统计更多的信息,比如平⽅和、⽅差、标准差
- cardinality 去重计数
#对全样数据进行聚合,eg. 统计nba球员的平均年龄
GET /nba/_search
{
"aggs": {
"avg_age": { #自定义的聚合名称
"avg": { #要使用的聚合函数
"field": "age" #要统计的字段
}
}
},
"size": 0
}
#对查询结果进行聚合,eg. 统计⽕箭队球员的平均年龄
GET /nba/_search
{
"query": {
"term": {
"team_name": "火箭队"
}
},
"aggs": {
"avgAge": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
#去重计数,eg. 统计某个活动的中奖人数
POST /raffle/_search
{
"query": {
"term": {
"activity_id": 123
}
},
"aggs": {
"coun_user": {
"cardinality": {
"field": "user_id"
}
}
},
"size": 0
}
#对全样数据进行聚合,eg. 统计nba球员的平均年龄
GET /nba/_search
{
"aggs": {
"avg_age": { #自定义的聚合名称
"avg": { #要使用的聚合函数
"field": "age" #要统计的字段
}
}
},
"size": 0
}
#对查询结果进行聚合,eg. 统计⽕箭队球员的平均年龄
GET /nba/_search
{
"query": {
"term": {
"team_name": "火箭队"
}
},
"aggs": {
"avgAge": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
#去重计数,eg. 统计某个活动的中奖人数
POST /raffle/_search
{
"query": {
"term": {
"activity_id": 123
}
},
"aggs": {
"coun_user": {
"cardinality": {
"field": "user_id"
}
}
},
"size": 0
}
嵌套聚合
#桶聚合嵌套指标聚合。先桶聚合按球队划分球员,再指标聚合得到每只球队球员的平均年龄,再按平均年龄对桶进行排序
GET /nba/_search
{
"aggs": {
"team_avg_age": {
"terms": {
"field": "team_name",
"order": {
"avg_age": "asc" #avg_age是年龄聚合的名称
}
},
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
},
"size": 0
}
#桶嵌套桶。先按省份划分用户,再在每个桶中按城市划分
GET /user/_search
{
"aggs": {
"count_province": {
"terms": {
"field": "province"
},
"aggs": {
"count_province_city": {
"terms": {
"field": "city"
}
}
}
}
},
"size": 0
}
#桶聚合嵌套指标聚合。先桶聚合按球队划分球员,再指标聚合得到每只球队球员的平均年龄,再按平均年龄对桶进行排序
GET /nba/_search
{
"aggs": {
"team_avg_age": {
"terms": {
"field": "team_name",
"order": {
"avg_age": "asc" #avg_age是年龄聚合的名称
}
},
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
},
"size": 0
}
#桶嵌套桶。先按省份划分用户,再在每个桶中按城市划分
GET /user/_search
{
"aggs": {
"count_province": {
"terms": {
"field": "province"
},
"aggs": {
"count_province_city": {
"terms": {
"field": "city"
}
}
}
}
},
"size": 0
}
百分比
#查看学生成绩的分布情况
POST /student/_search
{
"aggs": {
"percent_score": {
"percentiles": {
"field": "score",
"percents": [25, 50, 75] #指定百分比的分数,缺省时默认为 [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0]
}
}
},
"size": 0
}
#查看学生成绩的分布情况
POST /student/_search
{
"aggs": {
"percent_score": {
"percentiles": {
"field": "score",
"percents": [25, 50, 75] #指定百分比的分数,缺省时默认为 [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0]
}
}
},
"size": 0
}
图表
#eg. 统计学生成绩的分布情况。也属于桶聚合
GET /student/_search
{
"aggs":{
"socre_info":{
"histogram":{
"field": "score",
"interval": 20 #指定间距。[0,20),[20,40)...一个区间一个桶,区间上有文档时才划分为桶
}
}
},
"size" : 0
}
#按成绩划分区间(桶),统计每个区间上的文档,再计算每个桶内的平均分。桶聚合+指标聚合
GET /student/_search
{
"aggs": {
"socre_info": {
"histogram": {
"field": "score",
"interval": 20
},
"aggs": {
"avg_score": {
"avg": {
"field": "score"
}
}
}
}
},
"size": 0
}
#eg. 统计学生成绩的分布情况。也属于桶聚合
GET /student/_search
{
"aggs":{
"socre_info":{
"histogram":{
"field": "score",
"interval": 20 #指定间距。[0,20),[20,40)...一个区间一个桶,区间上有文档时才划分为桶
}
}
},
"size" : 0
}
#按成绩划分区间(桶),统计每个区间上的文档,再计算每个桶内的平均分。桶聚合+指标聚合
GET /student/_search
{
"aggs": {
"socre_info": {
"histogram": {
"field": "score",
"interval": 20
},
"aggs": {
"avg_score": {
"avg": {
"field": "score"
}
}
}
}
},
"size": 0
}