ElasticSearch在使用聚合功能的时候,排序的默认规则是依据命中的文档数量来做一个倒序获取;但有些统计场中并不是命中的文档数量越多其统计的结果就越大,因为很多时候聚合的数据是文档中的其他字段信息。
以上是一个按国家分类的聚合统计,统计的字段分别是销售金额和销售数量,由于每个订单存在的数量和金额都不是对等的,这时候就存在一个问题不能依据订单数量来作为排序依据。
既然是金额当然是需要按照金额量来排序,不是订单数量。所以在定义aggs聚合的情况还要再多定义一个排序聚合节点来做一个排序输出。
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
}
}
}
}
}
}
以上是官方文档描述的示例,对月份进行一个聚合分类,并对相应的price字段进行一个求和,最后针对聚合后的总价进行排序。在这里需要说明的是排序描述那部分,sales_bucket_sort是aggs排序的一个子集,这个名称是可以随意定义的;接下来的bucket_sort则是固定的,内部大部分内容也是固定主要关注的是total_sales,它是之前汇总的一个aggs子集名称。
接下来看回真实应用场是怎么做的
{
"query": {
"bool": {
"must": [
{
"range": {
"CreateTime": {
"gte": "2021-01-01T00:00:00",
"lte": "2021-03-25T23:59:59"
}
}
}
]
}
},
"aggs": {
"Year_group": {
"aggs": {
"sum_quantity": {
"sum": {
"field": "Quantity"
}
},
"sum_total": {
"sum": {
"field": "Total"
}
},
"query_bucket_sort": {
"bucket_sort": {
"sort": [
{
"sum_total": {
"order": "desc"
}
}
],
"size": 10,
"from": 0
}
}
},
"terms": {
"field": "Tag",
"include": "国家.*",
"size": 10,
"shard_size": 400
}
}
}
}
以上示例是根据国家标签进行一个分类汇总,然后对total字段进行汇总排序输出。在这里需要关注一个地方是顶层aggs的size和子层排序的size要对应好,如果只设置顶层的size最终排序得到的结果可以会少了,因为ElasticSearch默认对反回的数量都做了限制。