ES中的聚合查询,类似SQL的SUM/AVG/COUNT/GROUP BY分组查询,主要用于统计分析场景。
下面先介绍ES聚合查询的核心流程和核心概念。
1. ES聚合查询流程
ES聚合查询类似SQL的GROUP by,一般统计分析主要分为两个步骤:
- 分组
- 组内聚合
对查询的数据首先进行一轮分组,可以设置分组条件,例如:新生入学,把所有的学生按专业分班,这个分班的过程就是对学生进行了分组。
组内聚合,就是对组内的数据进行统计,例如:计算总数、求平均值等等,接上面的例子,学生都按专业分班了,那么就可以统计每个班的学生总数, 这个统计每个班学生总数的计算,就是组内聚合计算。
提示:分组类似SQL的group by语句设定的条件,组内聚合,就是在select编写的avg、sum、count统计函数;熟悉SQL语句都知道sum、count这些统计函数不一定要跟group by语句配合使用,单独使用统计函数等同于将所有数据分成一个组,直接对所有数据进行统计。
2. 核心概念
通过上面的聚合查询流程,下面是ES聚合的核心概念就很容易理解了
2.1. 桶
满足特定条件的文档的集合,叫做桶。
桶的就是一组数据的集合,对数据分组后,得到一组组的数据,就是一个个的桶。
提示:桶等同于组,分桶和分组是一个意思,ES使用桶代表一组相同特征的数据。
ES中桶聚合,指的就是先对数据进行分组,ES支持多种分组条件,例如:支持类似SQL的group by根据字段分组,当然ES比SQL更强大,支持更多的分组条件,以满足各种统计需求。
2.2. 指标
指标指的是对文档进行统计计算方式,又叫指标聚合。
桶内聚合,说的就是先对数据进行分组(分桶),然后对每一个桶内的数据进行指标聚合。
说白了就是,前面将数据经过一轮桶聚合,把数据分成一个个的桶之后,我们根据上面计算指标对桶内的数据进行统计。
常用的指标有:SUM、COUNT、MAX等统计函数。
借助SQL的统计语句理解桶和指标:
SELECT COUNT(*)
FROM order
GROUP BY shop_id
说明:
- COUNT(*) 相当于指标, 也叫统计指标。
- GROUP BY shop_id 相当于分桶的条件,也可以叫分组条件,相同shop_id的数据都分到一个桶内。
这条SQL语句的作用就是统计每一个店铺的订单数,所以SQL统计的第一步是根据group by shop_id这个条件,把shop_id(店铺ID)相同的数据分到一个组(桶)里面,然后每一组数据使用count(*)统计函数(指标)计算总数,最终得到每一个店铺的订单总数,ES也是类似的过程。
3.ES聚合查询语法
大家可以先大致了解下ES聚合查询的基本语法结构,后面的章节会介绍具体的用法。
{
"aggregations" : {
"<aggregation_name>" : {
"<aggregation_type>" : {
<aggregation_body>
}
[,"aggregations" : { [<sub_aggregation>]+ } ]? // 嵌套聚合查询,支持多层嵌套
}
[,"<aggregation_name_2>" : { ... } ]* // 多个聚合查询,每个聚合查询取不同的名字
}
}
说明:
- aggregations - 代表聚合查询语句,可以简写为aggs
- <aggregation_name> - 代表一个聚合计算的名字,可以随意命名,因为ES支持一次进行多次统计分析查询,后面需要通过这个名字在查询结果中找到我们想要的计算结果。
- <aggregation_type> - 聚合类型,代表我们想要怎么统计数据,主要有两大类聚合类型,桶聚合和指标聚合,这两类聚合又包括多种聚合类型,例如:指标聚合:sum、avg, 桶聚合:terms、Date histogram等等。
- <aggregation_body> - 聚合类型的参数,选择不同的聚合类型,有不同的参数。
- aggregation_name_2 - 代表其他聚合计算的名字,意思就是可以一次进行多种类型的统计。
下面看个简单的聚合查询的例子:
假设存在一个order索引,存储了每一笔汽车销售订单,里面包含了汽车颜色字段color.
GET /order/_search
{
"size" : 0, // 设置size=0的意思就是,仅返回聚合查询结果,不返回普通query查询结果。
"aggs" : { // 聚合查询语句的简写
"popular_colors" : { // 给聚合查询取个名字,叫popular_colors
"terms" : { // 聚合类型为,terms,terms是桶聚合的一种,类似SQL的group by的作用,根据字段分组,相同字段值的文档分为一组。
"field" : "color" // terms聚合类型的参数,这里需要设置分组的字段为color,根据color分组
}
}
}
}
上面使用了terms桶聚合,而且没有明确指定指标聚合函数,默认使用的是Value Count聚合指标统计文档总数, 整个统计的意思是统计每一种汽车颜色的销量。
等价SQL如下:
select count(color) from order group by color
查询结果如下
{
...
"hits": { // 因为size=0,所以query查询结果为空
"hits": []
},
"aggregations": { // 聚合查询结果
"popular_colors": { // 这个就是popular_colors聚合查询的结果,这就是为什么需要给聚合查询取个名字的原因,如果有多个聚合查询,可以通过名字查找结果
"buckets": [ // 因为是桶聚合,所以看到返回一个buckets数组,代表分组的统计情况,下面可以看到每一种颜色的销量情况
{
"key": "red",
"doc_count": 4 // 红色的汽车销量为4
},
{
"key": "blue",
"doc_count": 2
},
{
"key": "green",
"doc_count": 2
}
]
}
}
}