I have a ElasticSearch Query that is working well (curl), is my first Query,
First I am filtering by Organization (Multitenancy), then group by Customer, Finally sum the amount of the sales but I only want to have the 3 best customers.
My question is.. How to build the aggregation with the AggregationBuilders to get “bucket_sort” statement. I got the sales grouping by customer with Java API.
Elastic Query is:
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 } } } } } } } }'
My Java Code:
@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(); }
Advertisement
Answer
I hope I got your question right. Try adding “order” to your groupBy agg:
AggregationBuilder groupBy = AggregationBuilders.terms("by_customer").field("customer_id").subAggregation(sum).order(Terms.Order.aggregation("sum_total", false));
One more thing, if you want the top 3 clients than your .size(3)
should be set on groupBy agg as well and not on sorting. like that:
AggregationBuilder groupBy = AggregationBuilders.terms("by_customer").field("customer_id").subAggregation(sum).order(Terms.Order.aggregation("sum_total", false)).size(3);