Converting 7x. into 8.x Java client code. Getting the counts of individual buckets

In our journey of converting 7.x client code into 8.x code we ran into one more challenge.

Observe the following code that converts aggregation data retrieved from the client into a list of our Agg dto objects.

public static @NotNull List<Agg> toAggList(final @NotNull Map<String, Aggregate> aggregations) {
        if (aggregations.isEmpty()) {
            return Collections.emptyList();
        }
        final var results = new ArrayList<Agg>();
        for (final var aggItem : aggregations.entrySet()) {
            final var aggregationName = aggItem.getKey();
            final var aggBuilder = Agg.builder()
                    .name(aggregationName);
            final var aggregation = aggregations.get(aggregationName);
            // REMARK: map to aggBuckets to get the count of each aggregation bucket.
            // The original 7.x code iterated over the buckets of a terms aggregation here.

            final var aggBuckets= new ArrayList<AggBucket>();
            aggBuilder.detail(aggBuckets);
            results.add(aggBuilder.build());
        }
        return results;
    }

The Orginal 7.X code had the following:

...
for (final Aggregation aggItem : aggregations.asList()) {
            final var aggregationName = aggItem.getName();
            final var aggObject = Agg.builder()
                    .aggName(aggregationName)
                    .build();
            final Terms aggregation = aggregations.get(aggregationName);
            final var details = new ArrayList<AggBucket>();
            for (final var entry : aggregation.getBuckets()) {
                AggBucket aggBucket = new AggBucket();
                aggBucket.setValue((String) entry.getKey());     // Term
                aggBucket.setCount((int) entry.getDocCount()); // Doc count
                details.add(aggBucket);
            }
...

The problem is how to get to the Terms aggregation to get to the list of buckets to get the count.

In the 8.x code I can check aggregation.isMultiTerms() and then do aggregation.multiTerms() and try to continue from there or do similar with dozens of other flavours terms aggregations.

What is the right approach?

Hey @Hans_Kruse

Does this help?

1 Like

Bonjour,

Oui. So simple, sterms option as in string terms.

That solves it. Merci beaucoup.

  public static @NotNull List<Agg> toAggList(final @NotNull Map<String, Aggregate> aggregations) {
        if (aggregations.isEmpty()) {
            return Collections.emptyList();
        }
        return aggregations.entrySet().stream()
                // call me paranoid for filtering a bit much on null or empty
                .filter(Objects::nonNull)
                .filter(item -> item.getValue() != null)
                .filter(item -> item.getValue().sterms() != null)
                .filter(item -> item.getValue().sterms().buckets() != null)
                .filter(item -> item.getValue().sterms().buckets().isArray())
                .filter(item -> !item.getValue().sterms().buckets().array().isEmpty())
                .map(item -> Agg.builder()
                        .name(item.getKey())
                        .detail(item
                                .getValue()
                                .sterms()
                                .buckets()
                                .array()
                                .stream()
                                .filter(Objects::nonNull)
                                .map(bucket -> AggBucket.builder()
                                        .value(bucket.key().stringValue())
                                        .count(bucket.docCount())
                                        .build())
                                .toList())
                        .build()).toList();
    }
1 Like