类似于 DSL 查询表达式,聚合也有 可组合 的语法:独立单元的功能可以被混合起来提供你需要的自定义行为。这意味着只需要学习很少的基本概念,就可以得到几乎无尽的组合。
要掌握聚合,你只需要明白两个主要的概念:
桶(Buckets)满足特定条件的文档的集合指标(Metrics)对桶内的文档进行统计计算
这就是全部了!每个聚合都是一个或者多个桶和零个或者多个指标的组合。翻译成粗略的SQL语句来解释吧:
桶在概念上类似于 SQL 的分组(GROUP BY),而指标则类似于 COUNT()
、 SUM()
、 MAX()
等统计方法。
1.桶
桶也可以被嵌套在其他桶里面,提供层次化的或者有条件的划分方案。例如,辛辛那提会被放入俄亥俄州这个桶,而 整个 俄亥俄州桶会被放入美国这个桶。
Elasticsearch 有很多种类型的桶,能让你通过很多种方式来划分文档(时间、最受欢迎的词、年龄区间、地理位置等等)。其实根本上都是通过同样的原理进行操作:基于条件来划分文档
2.指标
桶能让我们划分文档到有意义的集合,但是最终我们需要的是对这些桶内的文档进行一些指标的计算。分桶是一种达到目的的手段:它提供了一种给文档分组的方法来让我们可以计算感兴趣的指标。
大多数 指标 是简单的数学运算(例如最小值、平均值、最大值,还有汇总),这些是通过文档的值来计算。在实践中,指标能让你计算像平均薪资、最高出售价格、95%的查询延迟这样的数据。
3.桶和指标的组合
聚合 是由桶和指标组成的。 聚合可能只有一个桶,可能只有一个指标,或者可能两个都有。也有可能有一些桶嵌套在其他桶里面。例如,我们可以通过所属国家来划分文档(桶),然后计算每个国家的平均薪酬(指标)。
由于桶可以被嵌套,我们可以实现非常多并且非常复杂的聚合:
1.通过国家划分文档(桶)
2.然后通过性别划分每个国家(桶)
3.然后通过年龄区间划分每种性别(桶)
4.最后,为每个年龄区间计算平均薪酬(指标)
最后将告诉你每个 <国家, 性别, 年龄>
组合的平均薪酬。所有的这些都在一个请求内完成并且只遍历一次数据!
//根据颜色对汽车进行分组
可能会注意到我们将 size
设置成 0 。我们并不关心搜索结果的具体内容,所以将返回记录数设置为 0 来提高查询速度。 设置 size: 0
与 Elasticsearch 1.x 中使用 count
搜索类型等价。
GET /cars/_search
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
}
}
}
}
4.添加度量指标
//每种颜色汽车的平均价格是多少
GET /cars/_search
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color"
},
"aggs":{
"avg_price":{
"avg":{
"field": "price"
}
}
}
}
}
}
5.嵌套桶
//获取每个颜色的汽车制造商的分布及颜色平均价
GET /cars/_search
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color"
},
"aggs":{
"avg_price":{
"avg":{
"field": "price"
}
},
"makes":{
"terms": {
"field": "make"
}
}
}
}
}
}
//根据颜色,制造商进行分组,然后获取平均价格
GET /cars/_search
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color"
},
"aggs":{
"makes":{
"terms": {
"field": "make"
},
"aggs": {
"avg_price":{
"avg":{
"field": "price"
}
}
}
}
}
}
}
}
为每个汽车生成商计算最低和最高的价格
GET /cars/_search
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": { "avg": { "field": "price" }
},
"make" : {
"terms" : {
"field" : "make"
},
"aggs" : {
"min_price" : { "min": { "field": "price"} },
"max_price" : { "max": { "field": "price"} }
}
}
}
}
}
}
有了这两个桶,我们可以对查询的结果进行扩展并得到以下信息:
- 有四辆红色车。
- 红色车的平均售价是 $32,500 美元。
- 其中三辆红色车是 Honda 本田制造,一辆是 BMW 宝马制造。
- 最便宜的红色本田售价为 $10,000 美元。
- 最贵的红色本田售价为 $20,000 美元。
条状图
//根据价格区间计算数量及总价
我们可能会注意到空的区间,比如:$40,000-60,000,没有出现在响应中。 histogram
桶默认会忽略它,因为它有可能会导致不希望的潜在错误输出。
GET /cars/_search
{
"size" : 0,
"aggs":{
"price":{
"histogram":{
"field": "price",
"interval": 20000
},
"aggs":{
"total_price": {
"sum": {
"field" : "price"
}
}
}
}
}
}
//按照欢迎度返回制造商列表以及它们各自的统计信息
GET /cars/_search
{
"size" : 0,
"aggs": {
"makes": {
"terms": {
"field": "make",
"size": 10
},
"aggs": {
"stats": {
"extended_stats": {
"field": "price"
}
}
}
}
}