如何将存储桶排序添加到查询聚合

时间:2018-10-27 15:24:19

标签: java elasticsearch

我有一个运作良好的ElasticSearch查询(curl),这是我的第一个查询,

首先,我要按组织(多租户)进行过滤,然后按客户进行分组,最后对销售额进行总计,但我只想拥有3个最佳客户。

我的问题是..如何使用AggregationBuilders构建聚合以获取“ bucket_sort”语句。我使用Java API按客户进行了销售分组。

弹性查询为:

 curl -X POST 'http://localhost:9200/sales/sale/_search?pretty'  -H 'Content-Type: application/json' -d '
     {
         "aggs": {

     "filtered": {
       "filter": {
         "bool": {
           "must": [
             {
               "term": {
                 "organization_id": "15"
               }
             }
           ]
         }
       },
       "aggs": {
               "by_customer": {
                 "terms": {
                   "field": "customer_id"
                 },
                  "aggs": {
                      "sum_total" : {
                          "sum": {
                              "field": "amount"
                          }
                      },
                      "total_total_sort": {
                           "bucket_sort": {
                               "sort": [
                                 {"sum_total": {"order": "desc"}}
                               ],
                               "size": 3
                           }
                       }

                  }
               }
           }
     }
 }
 }'

我的Java代码:

@Test
public void queryBestCustomers() throws UnknownHostException {
    Client client = Query.client();
    AggregationBuilder sum = AggregationBuilders.sum("sum_total").field("amount");
    AggregationBuilder groupBy = AggregationBuilders.terms("by_customer").field("customer_id").subAggregation(sum);
    AggregationBuilder aggregation =
            AggregationBuilders
                    .filters("filtered",
                            new FiltersAggregator.KeyedFilter("must", QueryBuilders.termQuery("organization_id", "15"))).subAggregation(groupBy);

    SearchRequestBuilder requestBuilder = client.prepareSearch("sales")
            .setTypes("sale")
            .addAggregation(aggregation);
    SearchResponse response = requestBuilder.execute().actionGet();
}

2 个答案:

答案 0 :(得分:1)

希望您的问题正确。 尝试将“订单”添加到您的组通过agg:

AggregationBuilder groupBy = AggregationBuilders.terms("by_customer").field("customer_id").subAggregation(sum).order(Terms.Order.aggregation("sum_total", false));

还有一件事情,如果您希望排名前三位的客户多于.size(3),那么也应该在groupBy agg上设置而不是在排序上。像这样:
AggregationBuilder groupBy = AggregationBuilders.terms("by_customer").field("customer_id").subAggregation(sum).order(Terms.Order.aggregation("sum_total", false)).size(3);

答案 1 :(得分:0)

正如提到的另一个答案,“订单”确实适用于您的用例。

然而,还有其他用例可能需要使用bucket_sort。例如,如果有人想要翻阅聚合存储桶。

由于 bucket_sort 是一个管道聚合,您不能使用 AggregationBuilders 来实例化它。相反,您需要使用 PipelineAggregatorBuilders。

您可以阅读有关 bucket sort/pipeline aggregation here 的更多信息。

以下代码中的“.from(50)”是如何分页浏览存储桶的示例。如果适用,这会导致存储桶中的项目从项目 50 开始。不包括“from”相当于“.from(0)”

BucketSortPipelineAggregationBuilder paging = PipelineAggregatorBuilders.bucketSort(
                    "paging", List.of(new FieldSortBuilder("sum_total").order(SortOrder.DESC))).from(50).size(10);
AggregationBuilders.terms("by_customer").field("customer_id").subAggregation(sum).subAggregation(paging);