Any Sample Java API client dynamic nested aggregation query building

Hi Team,

I have below query with me for which I am trying to build dynamically using Java API client.

{
"aggs": {
    "country_aggr": {
      "terms": {
        "field": "country",
        "size": 1000
      },
      "aggs": {
        "state_aggr": {
          "terms": {
            "field": "state",
              "size": 1000
          },
          "aggs": {
            "city_aggr": {
              "terms": {
                "field": "city",
                "size": 1000
              }
            }
          }
        }
      }
    }
  }
}

Any help would be appreciated.

Thanks,
Ram Prasad

Have a look at Switching from the Java High Level Rest Client to the new Java API Client | Elastic Blog

This might help you to find how to build your code.

An example of on agg in Java is also available at:

If you don't succeed, let us know and share what you did so far so we can iterate from that.

Hi dadoonet,

We are using Java API client. Currently we are preparing parent-child hierarchy based aggregation upfront using String (its not a recommended way) for different levels.
We tried to build this hierarchy dynamically based on the total number of fields, like below.

Aggregation aggr = Aggregation.of(t0 -> t0.terms(f0 -> f0.field(fields[0]).size(fieldSize[0])).aggregations(fields[1],
				t1 -> t1.terms(f1 -> f1.field(fields[1]).size(fieldSize[1])).aggregations(fields[2],
						t2 -> t2.terms(f2 -> f2.field(fields[2]).size(fieldSize[2])))));

But our requirement is, sub-aggregation should be appended to main aggregation within the iteration of fields.

Kindly let me know if my requirement is not clear.

Thanks,
Ram Prasad G

How should this look like using the QueryDSL?

It should look something like this,

Aggregation cityAggr = new Aggregation.Builder()
		.terms(new TermsAggregation.Builder().field(CITY).build())
		.build();
Map<String, Aggregation> cityAggrMap = new HashMap<>();
cityAggrMap.put(CITY_AGGR, cityAggr);

Aggregation stateAggr = new Aggregation.Builder()
		.terms(new TermsAggregation.Builder().field(STATE).build()).aggregations(cityAggrMap)
		.build();
Map<String, Aggregation> stateAggrMap = new HashMap<>();
stateAggrMap.put(STATE_AGGR, stateAggr);

Aggregation countryAggr = new Aggregation.Builder()
		.terms(new TermsAggregation.Builder().field(COUNTRY).build()).aggregations(stateAggrMap)
		.build();
Map<String, Aggregation> countryAggrMap = new HashMap<>();
countryAggrMap.put(COUNTRY_AGGR, countryAggr);

SearchRequest searchReq = SearchRequest.Builder().index(collection_name).size(0)
		.aggregations(countryAggrMap)
		.build();

In the above code, I am framing manually for 3 level of nested aggregation. This I need to frame dynamically.

Thanks,
Ram Prasad G

So you want something like this:

SearchResponse<Void> response = client.search(sr -> sr
                .index(indexName)
                .aggregations("country", a -> a.terms(ta -> ta.field("country"))
                        .aggregations("state", sa -> sa.terms(ta -> ta.field("state"))
                                .aggregations("city", ca -> ca.terms(ta -> ta.field("city")))
                        )
                )
        , Void.class);

But built depending on some conditions?