-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Description
Describe the feature: Running an avg aggregation when 0 documents/values match yields different values depending on connection type (TransportClient vs RestClient).
Elasticsearch version (bin/elasticsearch --version): 7.2.0 (and 6.x as well)
Plugins installed: []
JVM version (java -version): 11.0.3
OS version (uname -a if on a Unix-like system): Linux sascha 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Description of the problem including expected versus actual behavior: Calculation of avg metric over 0 documents yields NaN if connected to Elasticsearch using transport client, but Double.POSITIVE_INFINITY if using REST client. IMHO the result of an operation should not depend on the connection type to the Elasticsearch cluster.
This seems to be related to the fact that internally, Elasticsearch takes two different routes to create the result of an avg aggregation:
-
When using the TransportClient, this is done in
InternalAvgassum / count(https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalAvg.java#L69), where in case ofcount == 0Java returnsDouble.NaN -
Whereas when using REST, this is done in
ParsedAvg, explicitly settingDouble.POSITIVE_INFINITYas the default (https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/search/aggregations/metrics/ParsedAvg.java#L55)
Steps to reproduce: (see also attached elastic-avg.zip)
-
Run Elasticsearch via Docker as
run -it --rm -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e "discovery.type=single-node" -e "cluster.name=elasticsearch" docker.elastic.co/elasticsearch/elasticsearch:7.2.0 -
Index a sample document:
IndexRequest indexRequest = new IndexRequest("test").id("1").source(XContentFactory.jsonBuilder().startObject().field("value", 1).endObject());
client.index(indexRequest, RequestOptions.DEFAULT);
- Aggregate over a field with count
0:
protected static final AvgAggregationBuilder aggregation = AggregationBuilders.avg("test").field("value2");
- Run aggregation using TransportClient:
// execute aggregation over transport client
SearchResponse response = client.prepareSearch().addAggregation(aggregation).execute().actionGet();
Avg result = response.getAggregations().get("test");
// for transport client, the result is NaN
assertTrue(Double.isNaN(result.value()));
- Run aggregation using RestClient:
// execute aggregation over rest client
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchRequest.source(searchSourceBuilder);
searchSourceBuilder.aggregation(aggregation);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
Avg result = response.getAggregations().get("test");
// for rest client, the result is positive infinity
assertTrue(Double.isInfinite(result.value()));
Provide logs (if relevant):