9

I want to get aggregation in my java application.

First of all I've constracted REST query with curl. It's looks like:

curl -XGET 'localhost:9200/analysis/_search?pretty' -H 'Content-Type: 

application/json' -d'
{
  "size": 0,
  "query" : {
      "bool": {
          "must": [
              { "term" : { "customer_id" : 5117 } }
          ]
      }
  },
  "aggs": {
    "customer_id": {
      "terms": {
        "field": "customer_id", 
        "order": {
          "contract_sum": "desc"
        }
      },
      "aggs": {
        "contract_sum": {
          "sum": {
            "field": "contract_sum"
          }
        }
      }
    }
  }
}
'

It returned result as I expected

enter image description here

After that I've created some code in java

    Settings settings = Settings.builder().put("cluster.name", elasticProperties.getElasticClusterName()).build();
    log.info("Initializing ElasticSearch client");
    try (TransportClient client = new PreBuiltTransportClient(settings).addTransportAddress(new InetSocketTransportAddress(
            InetAddress.getByName(elasticProperties.getElasticTransportAddress()), elasticProperties.getElasticTransportPort()))) {

        // Base query
        log.info("Preparing query");
        SearchRequestBuilder requestBuilder = client.prepareSearch(elasticProperties.getElasticIndexName())
                .setTypes(elasticProperties.getElasticTypeName())
                .setSize(Top);

        // Add aggregations
        AggregationBuilder aggregation =
                AggregationBuilders
                        .terms("customer_id")
                        .field("customer_id")
                        //.order(Terms.Order.aggregation("customer_id", "contract_sum", false))
                        .subAggregation(
                                AggregationBuilders.sum("total_contract_sum")
                                .field("contract_sum")
                        );
        requestBuilder.addAggregation(aggregation);
        // Get response
        log.info("Executing query");
        SearchResponse response = requestBuilder.get();

        log.info("Query results:");

        Terms contractSums = response.getAggregations().get("customer_id");
        for (Terms.Bucket bucket : contractSums.getBuckets()) {
            log.info("  " + bucket.getKey() + " ");
        }

The question is:

How to get "contract_sum" aggregation value for current bucket item?

When I use debug tool in IntelliJ Idea it seems that it can

enter image description here

Please help me with code example.

3 Answers 3

9

I've found solution with my Internet friends

log.info("Query results:");
Terms contractSums = response.getAggregations().get("customer_id");
for (Terms.Bucket bucket : contractSums.getBuckets()) {
    Sum aggValue = bucket.getAggregations().get("total_contract_sum");
    DecimalFormat formatter = new DecimalFormat("0.00");
    log.info("  " + bucket.getKey() + " " + formatter.format(aggValue.getValue()));
}
Sign up to request clarification or add additional context in comments.

1 Comment

how can i have a multi group by having multi query params to filter ?
0

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_bucket_aggregations.html

public List<StringBuilder> aggregation(String filterField, Object start, Object end, String... fields) throws IOException {
    List<StringBuilder> results = new LinkedList<>();
    SearchRequest searchRequest = new SearchRequest(this.index);
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    if (!StringUtils.isEmpty(filterField)){
        QueryBuilder queryBuilder = QueryBuilders.rangeQuery(filterField).gte(start).lte(end);
        searchSourceBuilder.query(queryBuilder);
    }
    AggregationBuilder aggregationBuilder = buildAggregation(fields, 0);

    if(aggregationBuilder == null)
        return results;
    searchSourceBuilder.aggregation(aggregationBuilder);

    searchRequest.source(searchSourceBuilder);
    SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);

    Terms terms = searchResponse.getAggregations().get(fields[0]);
    processBuckets(terms, new Stack<>(), results);
    return results;
}

public AggregationBuilder buildAggregation(String[] fields, int i) {
    if(i == fields.length - 1)
        return aggregationBuilder(fields[i]);

    return aggregationBuilder(fields[i]).subAggregation(buildAggregation(fields, i + 1));
}

private AggregationBuilder aggregationBuilder(String term) {
    return AggregationBuilders
            .terms(term)
            .field(term)
            .size(1000)
            .order(BucketOrder.count(false));
}

public void processBuckets(Terms terms, Stack<String> stack, List<StringBuilder> results) {
    if(terms != null) {
        for (Terms.Bucket bucket : terms.getBuckets()) {
            stack.push(bucket.getKeyAsString() + ":" + bucket.getDocCount() + ";");
            if(bucket.getAggregations().asList().isEmpty()) {
                StringBuilder result = new StringBuilder();
                for (String s : stack) {
                    result.append(s);
                }
                results.add(result);
            }

            for (Aggregation aggregation : bucket.getAggregations().asList()) {
                processBuckets((Terms) aggregation, stack, results);
            }
            stack.pop();
        }
    }
}

Comments

0
public Map<String, Collection<Map<String, Object>>> processAggregation(SearchResponse response) {
    Map<String,Collection<Map<String, Object>>> responseMap = new HashMap<>();
    try {
        if(response.getAggregations() != null) {
            for (Aggregation agg : response.getAggregations().asList()) {
                String key = agg.getName();
                Terms terms = response.getAggregations().get(key);
                Collection<Map<String, Object>> objects = new HashSet<>();
                Map<String, Object> result = new HashMap<>();
                for(Terms.Bucket bucket : terms.getBuckets()){
                    String extLabel = (String) bucket.getKey();
                    Object count = bucket.getDocCount();
                    result.put(extLabel,count);
                }
                objects.add(result);
                responseMap.put(key,objects);
            }
        }
        return responseMap;
    } catch (Exception e) {
        log.error("Unable to process search response");
    }
    return null;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.