前言
ES 聚合运算在面向 C 端的日常开发中,比较少碰到。在面向公司内部,或者数据报表的开发中可能会碰到。
ES 聚合运算主要分为三大类:
- 桶聚合(
Bucket aggregations
) - 指标聚合(
Metrics aggregations
) - 管道聚合(
Pipeline aggregations
)
因为管道聚合开发中实在没碰到过,本篇章就不介绍了。
桶聚合
桶聚合允许你根据一个或多个维度对数据进行分组。
ES 桶聚合有非常多的用法,这里挑出开发中相对常用的进行介绍。更多内容需要到 ES 桶聚合官网查阅
filters aggregation
多桶聚合,其中每个桶包含与查询匹配的文档。
例如查询 type=A,type=B 的 score 平均值
POST test10/_bulk
{"index": {}}
{"type":"A","score":12,"pid":13}
{"index": {}}
{"type":"A","score":42,"pid":13}
{"index": {}}
{"type":"A","score":55,"pid":12}
{"index": {}}
{"type":"B","score":14,"pid":13}
{"index": {}}
{"type":"B","score":1213,"pid":13}
{"index": {}}
{"type":"B","score":324,"pid":12}
GET test10/_search
{
"size": 0,
"query": {
"term": {
"pid": {
"value": 13
}
}
},
"aggs": {
"my_filters": {
"filters": {
"filters": {
"a_type": {
"term": {
"type.keyword": "A"
}
},
"b_type": {
"term": {
"type.keyword": "B"
}
}
}
},
"aggs": {
"avg_score": {
"avg": {
"field": "score"
}
}
}
}
}
}
term aggregation
term
聚合(terms aggregation
)是一种对数据进行分组的聚合操作,它基于一个字段的所有不同值(通常是关键词字段)来对数据进行分组。每个唯一的值都会成为一个“桶”(bucket),并且可以对这些桶进行各种统计分析,比如计数、求和、平均值等。
注:统计值只是一个预估值,非准确值。
基本用法
下面是一个基本的term
聚合的例子,它展示了如何在products
索引中根据category
字段的不同值来聚合文档,并计算每个类别的文档数量:
POST /products/_search
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category.keyword"
}
}
}
}
在这个例子中,size
设置为0是因为我们只对聚合结果感兴趣,不需要返回任何文档。aggs
字段定义了聚合操作,其中 categories
是我们给这个聚合操作起的名字,terms
指定了我们想要进行的聚合类型,field
指定了我们想要聚合的字段。
配置选项
term
聚合有一些重要的配置选项:
field
:指定要聚合的字段。size
:指定返回的桶的数量。默认是10,可以设置一个更大的数字来返回更多的桶。shard_size
:在分片级别上设置桶的数量,这通常比size
大,因为每个分片会先收集桶,然后减少到size
指定的数量。min_doc_count
:指定每个桶至少需要包含的文档数量。如果设置为1,那么即使某个关键词只出现了一次也会被包含在结果中。order
:指定桶的排序方式。可以按照_count
(默认,按桶中的文档数量降序排序,不应该使用升序排序)、_term
(按词条字典顺序排序)或者自定义脚本等方式排序。
子聚合
term
聚合可以包含子聚合,这意味着你可以在每个桶的基础上进一步进行聚合。例如,你可以先按category
字段聚合,然后在每个类别内部按price
字段进行统计分析:
POST /products/_search
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category.keyword",
"size": 10
},
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
在这个例子中,categories
聚合下的average_price
子聚合会计算每个类别的平均价格。
注意事项
term
聚合通常用于keyword
类型的字段,因为这些字段是全文本的,不会进行分词。- 对于文本字段,你可能需要先将文本字段的分词结果聚合起来,然后再进行
term
聚合。 - 大量的唯一值可能会导致大量的桶,这可能会消耗大量的内存和网络带宽,因此需要合理设置
size
和shard_size
。
指标聚合
指标聚合一般是用于对某一个字段进行算术运算。例如:求均值、求和、求最大值、求最小值、求文档数。
本篇只会选择其中一个介绍,其他内容大差不差。更详细信息请自行阅读 ES 指标聚合官网
求所有指标
GET test10/_search
{
"size": 0,
"aggs": {
"my_stat": {
"stats": {
"field": "score"
}
}
}
}
返回
{
......
"aggregations" : {
"my_stat" : {
"count" : 6,
"min" : 12.0,
"max" : 1213.0,
"avg" : 276.6666666666667,
"sum" : 1660.0
}
}
}