文章目录
官方文档
概述
在 Elasticsearch 中,bucket_sort
聚合是一种父管道聚合(Parent Pipeline Aggregation),用于对其父多桶聚合的桶进行排序。可以指定一个或多个排序字段,并根据这些字段对桶进行排序。每个桶可以基于其 _key
、_count
或其子聚合进行排序。
此外,还可以设置 from
和 size
参数,以限制返回的桶的数量。
1. Bucket Sort 聚合概述
bucket_sort
聚合会在所有非管道聚合执行后进行排序。这意味着排序只会应用于从父聚合中返回的桶。例如,如果父聚合是 terms
聚合,并且其 size
设置为 10,那么 bucket_sort
聚合只会对这 10 个返回的 term
桶进行排序。
2. 语法
以下是 bucket_sort
聚合的基础语法:
{
"bucket_sort": {
"sort": [
{ "sort_field_1": { "order": "asc" } },
{ "sort_field_2": { "order": "desc" } },
"sort_field_3"
],
"from": 1,
"size": 3
}
}
sort
: 这是一个字段列表,用于指定排序的依据。你可以选择排序字段的升序或降序,或者使用桶路径字段(例如,_count
或_key
)。from
: 从指定的位置开始,截断在此之前的桶。size
: 返回的桶的数量。如果没有指定,默认返回所有父聚合的桶。
3. bucket_sort
聚合的常用参数
参数名 | 描述 | 是否必需 | 默认值 |
---|---|---|---|
sort |
排序字段列表,用于确定桶的排序顺序。 | 可选 | 无 |
from |
用于截断前面桶的位置。 | 可选 | 0 |
size |
返回的桶数量。 | 可选 | 所有桶 |
gap_policy |
数据中缺失值时的处理策略。 | 可选 | 通过指定策略控制(详见下文)。 |
4. 示例 1:按总销售额排序并截取前三个月
假设有一个包含销售数据的索引,且希望按照每个月的总销售额进行排序,并返回销售额最高的前三个月。可以使用以下查询:
POST /sales/_search
{
"size": 0,
"aggs": {
"sales_per_month": {
"date_histogram": {
"field": "date",
"calendar_interval": "month"
},
"aggs": {
"total_sales": {
"sum": {
"field": "price"
}
},
"sales_bucket_sort": {
"bucket_sort": {
"sort": [
{ "total_sales": { "order": "desc" } }
],
"size": 3
}
}
}
}
}
}
sales_per_month
:使用date_histogram
聚合按照月份对销售数据进行分桶。total_sales
:计算每个月的总销售额。sales_bucket_sort
:应用bucket_sort
聚合,按total_sales
的降序进行排序,并限制返回前 3 个桶。
结果示例
{
"took": 82,
"timed_out": false,
"_shards": ...,
"hits": ...,
"aggregations": {
"sales_per_month": {
"buckets": [
{
"key_as_string": "2015/01/01 00:00:00",
"key": 1420070400000,
"doc_count": 3,
"total_sales": {
"value": 550.0
}
},
{
"key_as_string": "2015/03/01 00:00:00",
"key": 1425168000000,
"doc_count": 2,
"total_sales": {
"value": 375.0
}
},
{
"key_as_string": "2015/02/01 00:00:00",
"key": 1422748800000,
"doc_count": 2,
"total_sales": {
"value": 60.0
}
}
]
}
}
}
在这个例子中,返回了按照销售总额降序排序后的前三个月数据。
5. 示例 2:仅截取指定数量的桶
有时可能只想对返回的桶进行截断,而不对其排序。可以通过设置 from
和 size
参数来实现,只截取特定范围的桶。例如,以下查询将返回第二个月的销售数据:
POST /sales/_search
{
"size": 0,
"aggs": {
"sales_per_month": {
"date_histogram": {
"field": "date",
"calendar_interval": "month"
},
"aggs": {
"bucket_truncate": {
"bucket_sort": {
"from": 1,
"size": 1
}
}
}
}
}
}
结果示例
{
"took": 11,
"timed_out": false,
"_shards": ...,
"hits": ...,
"aggregations": {
"sales_per_month": {
"buckets": [
{
"key_as_string": "2015/02/01 00:00:00",
"key": 1422748800000,
"doc_count": 2
}
]
}
}
}
此查询将返回第二个月的桶,其他桶将被截断。
6. 处理数据中的缺失值(gap_policy)
在一些聚合中,数据可能存在缺失值。bucket_sort
聚合提供了 gap_policy
参数,用于处理这种情况。你可以设置以下选项:
skip
:跳过缺失的值。insert_zeros
:为缺失的值插入零。
例如,如果你希望跳过缺失的桶,可以这样设置:
{
"bucket_sort": {
"sort": [
{ "total_sales": { "order": "desc" } }
],
"gap_policy": "skip"
}
}
其他参考DSL
小结
bucket_sort
聚合提供了一种灵活的方式来对 Elasticsearch 聚合的结果进行排序,并且可以截断结果集,返回最感兴趣的桶。这对于数据分析和报告尤其有用,尤其是只关心排名靠前的数据时。通过合理配置 from
、size
和 sort
参数,可以高效地获取所需的结果。