聚合提供了从数据中分组和提取数据的能力,最简单的聚合方法大致等于sql group by和sql聚合函数。在ES中,如果有执行搜索返回his()命中结果,并且同时返回聚合结果,把一个响应中的所有his(命中结果)分隔开的能力。这是非常强大且有效的,我们可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的API来避免网络往返。
语法:
"aggregations":{
"<aggregation_name>":{
"<aggregation_type>":{
<aggregation_body>
}
[,"meta":{ [<meta_data_body>] }]?
[,"aggragations":{ [<sub_aggragation>]+ }]?
}
[,"<aggragation_name_2>":{...}]*
}
语法解释:
1)<aggregation_name>:为某一个聚合起一个名字
2)<aggregation_type>:表示什么类型的聚合,聚合类型有很多,可以参看文档
3)<aggregation_body>:聚合体内容
4)meta:聚合元数据
5)sub_aggragation:子聚合
例1:搜索address中包含mill的所有人的年龄分布
GET /bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
}
}
}
解析:
1)aggs:聚合关键字
2)ageAgg:聚合名称
3)terms:聚合类型
查询结果,如图:命中记录4个,按照年龄有三条,其中38岁的有2个
例2:搜索address中包含mill的所有人的年龄分布以及平均年龄
聚合可以包含多个聚合
GET /bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
}
}
}
结果如图:
例3:搜索address中包含mill的所有人的年龄分布以及平均年龄和平均薪资
GET /bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
},
"balanceAvg":{
"avg": {
"field": "balance"
}
}
}
}
结果如图:
例4:搜索address中包含mill的所有人的年龄分布以及平均年龄,不显示搜索数据只看聚合结果
GET /bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
},
"balanceAvg":{
"avg": {
"field": "balance"
}
}
},
"size": 0
}
结果如图:
例5:按照年龄聚合,并且求这些年龄段的平均薪资
这个需求使用到了子聚合
GET /bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
},
"aggs": {
"banlanceAvg": {
"avg": {
"field": "balance"
}
}
}
}
},
"size": 0
}
结果如图:
注意:
对于字段类型为keyword/text的字段进行聚合的时候,会报错 "Can't load fielddata on [brandName] because fielddata is unsupported on fields of type [keyword]. Use doc values instead." 出现该错误是因为ES 5.x之后,对聚合所依据的字段用单独的数据结构(fielddata)缓存到内存里了,但是在text字段上默认是禁用的,如果有需要单独开启,这样做的目的是为了节省内存空间。
解决办法:
方案一:对text类型的字段开启fielddata属性
如图:
未实际测试
方案二:使用内置keyword字段
如图,在查询的时候使用keyword
方案三:如果有指定"doc_values" : false,将其改成true