Java API: how to access sub aggregations from FilterAggregate objects

I am in the process of migrating from the High Level REST API to the Java API. Although it is going ok despite not having many examples in the docs, there is one problem I can't figure out.

When you send a search request that contains a filter aggregation that contains one or more sub aggregations, I don't know how to access those sub aggregations from the search response.

The search response object gives access to the top level aggregations (Aggregate objects). I can also access the FilterAggregate objects with the filter() method, but those only allow me to get the docCount() from the response. I would expect an aggregations() method that returns Map<String,Aggregate>, in order to access the Aggregate objects under the filter. In the HLRC this used to be possible.

Many thanks for helping me out.

I also don't think I have a map, but I can put all the results of subaggs in my own map.

    Terms aggregation = response.getAggregations().get("root-aggs");
    var mapResult = new HashMap<String, Long>();
    for (var aggs : aggregation.getBuckets()) {
      Terms subAggs = aggs.getAggregations().get("key-sub-aggs");
      for (var bucket : subAggs.getBuckets()) {
        mapResult.put(bucket.getKeyAsString(), bucket.getDocCount());
      }
    }

@RabBit_BR , thanks for your reply. For StringTerm aggregations, it also works for me. Just not for Filter aggregations. Your code snippet looks like it's using the High Level Rest API (e.g. with getAggregations() instead of aggregations()), but for me the problem only happens for the Java API. Here is a code snippet, using your example:

co.elastic.clients.elasticsearch.core.SearchResponse<HashMap> searchResponse = doSearchCall();
Aggregate aggregate = searchResponse.aggregations().get("root-aggs"); //This works
if(aggregate.isFilter()) {
	FilterAggregate filterAggregate = aggregate.filter();
	Aggregate subAggregate = filterAggregate.aggregations().get("key-sub-aggs"); //This does not work.
}

Why do you not use High Level Rest API ?

Because the High Level REST Client is deprecated.

Sorry,

Maybe this:

    var mapResult = new HashMap<String, Long>();
    for (var rootBucket : aggs.get("root-aggs").sterms().buckets().array()){
     var subAggsBucket = rootBucket.aggregations().get("key-sub-aggs").sterms().buckets().array();
      for (var subBucket : subAggsBucket) {
        mapResult.put(subBucket.key(), subBucket.docCount());
      }
    }

Thanks for thinking along @RabBit_BR .

So for String Term Aggregations I can indeed access the buckets and their sub aggregations via the Java API. It's different however for Filter Aggregations.

I see that this is fixed now since 7.17, very nice.

1 Like

Hi, how are you building subaggregations with filter aggregation request.