Skip to content

Commit 1243704

Browse files
authored
Don't validate internal stats if they are empty (#113846) (#114137)
Fixes a validation step that might prevent creating empty aggregations iif the output format does not allows negative numbers.
1 parent 5478750 commit 1243704

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

docs/changelog/113846.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 113846
2+
summary: Don't validate internal stats if they are empty
3+
area: Aggregations
4+
type: bug
5+
issues:
6+
- 113811

server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalStats.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public InternalStats(
7474
}
7575

7676
private void verifyFormattingStats() {
77-
if (format != DocValueFormat.RAW) {
77+
if (format != DocValueFormat.RAW && count != 0) {
7878
verifyFormattingStat(Fields.MIN, format, min);
7979
verifyFormattingStat(Fields.MAX, format, max);
8080
verifyFormattingStat(Fields.AVG, format, getAvg());

server/src/test/java/org/elasticsearch/search/aggregations/metrics/ExtendedStatsAggregatorTests.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,20 @@
1313
import org.apache.lucene.document.SortedNumericDocValuesField;
1414
import org.apache.lucene.tests.index.RandomIndexWriter;
1515
import org.apache.lucene.util.NumericUtils;
16+
import org.elasticsearch.common.time.DateFormatter;
1617
import org.elasticsearch.core.CheckedConsumer;
18+
import org.elasticsearch.index.mapper.DateFieldMapper;
1719
import org.elasticsearch.index.mapper.MappedFieldType;
1820
import org.elasticsearch.index.mapper.NumberFieldMapper;
1921
import org.elasticsearch.search.aggregations.AggregatorTestCase;
2022
import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper;
2123

2224
import java.io.IOException;
25+
import java.util.Map;
2326
import java.util.function.Consumer;
2427

2528
import static java.util.Collections.singleton;
29+
import static org.elasticsearch.search.aggregations.AggregationBuilders.stats;
2630

2731
public class ExtendedStatsAggregatorTests extends AggregatorTestCase {
2832
private static final double TOLERANCE = 1e-5;
@@ -48,6 +52,37 @@ public void testEmpty() throws IOException {
4852
});
4953
}
5054

55+
public void testEmptyDate() throws IOException {
56+
DateFormatter.forPattern("epoch_millis");
57+
final MappedFieldType ft = new DateFieldMapper.DateFieldType(
58+
"field",
59+
true,
60+
true,
61+
false,
62+
true,
63+
DateFormatter.forPattern("epoch_millis"),
64+
DateFieldMapper.Resolution.MILLISECONDS,
65+
null,
66+
null,
67+
Map.of()
68+
);
69+
testCase(ft, iw -> {}, stats -> {
70+
assertEquals(0d, stats.getCount(), 0);
71+
assertEquals(0d, stats.getSum(), 0);
72+
assertEquals(Float.NaN, stats.getAvg(), 0);
73+
assertEquals(Double.POSITIVE_INFINITY, stats.getMin(), 0);
74+
assertEquals(Double.NEGATIVE_INFINITY, stats.getMax(), 0);
75+
assertEquals(Double.NaN, stats.getVariance(), 0);
76+
assertEquals(Double.NaN, stats.getVariancePopulation(), 0);
77+
assertEquals(Double.NaN, stats.getVarianceSampling(), 0);
78+
assertEquals(Double.NaN, stats.getStdDeviation(), 0);
79+
assertEquals(Double.NaN, stats.getStdDeviationPopulation(), 0);
80+
assertEquals(Double.NaN, stats.getStdDeviationSampling(), 0);
81+
assertEquals(0d, stats.getSumOfSquares(), 0);
82+
assertFalse(AggregationInspectionHelper.hasValue(stats));
83+
});
84+
}
85+
5186
public void testRandomDoubles() throws IOException {
5287
MappedFieldType ft = new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.DOUBLE);
5388
final ExtendedSimpleStatsAggregator expected = new ExtendedSimpleStatsAggregator();

server/src/test/java/org/elasticsearch/search/aggregations/metrics/StatsAggregatorTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import org.apache.lucene.tests.index.RandomIndexWriter;
1818
import org.apache.lucene.util.NumericUtils;
1919
import org.elasticsearch.common.settings.Settings;
20+
import org.elasticsearch.common.time.DateFormatter;
2021
import org.elasticsearch.core.CheckedConsumer;
22+
import org.elasticsearch.index.mapper.DateFieldMapper;
2123
import org.elasticsearch.index.mapper.MappedFieldType;
2224
import org.elasticsearch.index.mapper.NumberFieldMapper;
2325
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
@@ -72,6 +74,30 @@ public void testEmpty() throws IOException {
7274
}, ft);
7375
}
7476

77+
public void testEmptyDate() throws IOException {
78+
DateFormatter.forPattern("epoch_millis");
79+
final MappedFieldType ft = new DateFieldMapper.DateFieldType(
80+
"field",
81+
true,
82+
true,
83+
false,
84+
true,
85+
DateFormatter.forPattern("epoch_millis"),
86+
DateFieldMapper.Resolution.MILLISECONDS,
87+
null,
88+
null,
89+
Map.of()
90+
);
91+
testCase(stats("_name").field(ft.name()), iw -> {}, stats -> {
92+
assertEquals(0d, stats.getCount(), 0);
93+
assertEquals(0d, stats.getSum(), 0);
94+
assertEquals(Float.NaN, stats.getAvg(), 0);
95+
assertEquals(Double.POSITIVE_INFINITY, stats.getMin(), 0);
96+
assertEquals(Double.NEGATIVE_INFINITY, stats.getMax(), 0);
97+
assertFalse(AggregationInspectionHelper.hasValue(stats));
98+
}, ft);
99+
}
100+
75101
public void testRandomDoubles() throws IOException {
76102
final MappedFieldType ft = new NumberFieldMapper.NumberFieldType("field", NumberType.DOUBLE);
77103
final SimpleStatsAggregator expected = new SimpleStatsAggregator();

0 commit comments

Comments
 (0)