opensearch-project / opensearch-java

Java Client for OpenSearch
Apache License 2.0
119 stars 182 forks source link

Composite Aggregation after key ignored #785

Open assafcoh opened 9 months ago

assafcoh commented 9 months ago

What is the bug?

when searching with composite aggregation the supplied afterKey is ignored and we always get back the same initial afterKey. Therefore, iterating with composite aggregation until the afterKey is null, leads to an infinite loop

client version

we encountered this bug with client version 2.6.0, 2.70 and also after upgrading to the latest 2.8.1 client version

How can one reproduce the bug?

search with composite aggregation in a loop until the afterKey is null. Since the afterKey is ignored, it will always search from the beginning and repeatedly return the same afterKey

What is the expected behavior?

the afterKey should should be considered, so that after each search we get back the "next" afterKey

workaround

Unfortunately we switched back to the rest client :(

Code sample to reproduce infinite loop

List<Map<String, CompositeAggregationSource>> compositeAggSourceList = new ArrayList<>();

compositeAggSourceList.add(Collections.singletonMap("tenant_id", new CompositeAggregationSource.Builder()
                .terms(new TermsAggregation.Builder()
                        .field("tenant_id")
                        .build())
        .build()));
compositeAggSourceList.add(Collections.singletonMap("user_id", new CompositeAggregationSource.Builder()
        .terms(new TermsAggregation.Builder()
                .field("user_id")
                .build())
        .build()));

CompositeAggregate compositeAggregate = null;
do {
    // update the composite aggregation after key
    Map<String, String> afterKey;
    if(compositeAggregate !=null){
        afterKey = compositeAggregate.afterKey().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
                e -> new String(e.getValue().toString())));
    } else {
        afterKey = null;
    }

    SearchRequest searchRequest = new SearchRequest.Builder()
            .index("example-index")
            .size(0)
            .aggregations("composite-agg", new Aggregation.Builder()
                    .composite(c-> afterKey !=null ? c.sources(compositeAggSourceList).size(10).after(afterKey) : c.sources(compositeAggSourceList).size(10))
                    .aggregations("incidents",
                            a -> a.sum(t -> t.field("incidents")))
                    .aggregations("activities",
                            a -> a.sum(t -> t.field("activities")))
                    .build())
            .build();

    SearchResponse<Map> searchResponse = openSearchClient.get().search(searchRequest, Map.class);

    compositeAggregate = searchResponse.aggregations().get("composite-agg").composite();

    // our internal logic...

} while (compositeAggregate.afterKey()!=null);
assafcoh commented 8 months ago

composite aggregation is the only way to paginate aggregations. This is a major bug, Is there a fix estimate?

dblock commented 8 months ago

@assafcoh Nobody has picked this up yet, care to help? Maybe start by adding a (failing) test?

assafcoh commented 2 months ago

Unfortunately, i am not able to contribute here.

However, this bug means there is no way to paginate aggregations with this java client. In my opinion, this is a central feature and should be given higher priority.

amcgreevy-r7 commented 2 months ago

@dblock Has there been any movement on this? This is a core feature that is really needed.

dblock commented 2 months ago

@amcgreevy-r7 Would love your help, see above.