Skip to content

Commit 3186837

Browse files
author
Christoph Büscher
committed
Fix range queries on runtime double field (#71915)
DoubleScriptFieldRangeQuery which is used on runtime fields of type "double" currently uses simple double type comparison for checking its upper and lower bounds. Unfortunately it seems that -0.0 == 0.0, but when we want to exclude a 0.0 bound via "lt" the generated range query uses -0.0 as its upper bound which erroneously includes the 0.0 value. We can use `Double.compare` instead which seems to handle this edge case well. Closes #71786
1 parent 37dd7d8 commit 3186837

File tree

3 files changed

+62
-8
lines changed

3 files changed

+62
-8
lines changed

x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/query/DoubleScriptFieldRangeQuery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public DoubleScriptFieldRangeQuery(
3232
@Override
3333
protected boolean matches(double[] values, int count) {
3434
for (int i = 0; i < count; i++) {
35-
if (lowerValue <= values[i] && values[i] <= upperValue) {
35+
if (Double.compare(lowerValue, values[i]) <= 0 && Double.compare(values[i], upperValue) <= 0) {
3636
return true;
3737
}
3838
}

x-pack/plugin/runtime-fields/src/test/java/org/elasticsearch/xpack/runtimefields/query/DoubleScriptFieldRangeQueryTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ public void testMatches() {
6666
assertTrue(query.matches(new double[] { 2, 5 }, 2));
6767
assertTrue(query.matches(new double[] { 5, 2 }, 2));
6868
assertFalse(query.matches(new double[] { 5, 2 }, 1));
69+
70+
// test some special cases around 0.0
71+
query = new DoubleScriptFieldRangeQuery(randomScript(), leafFactory, "test", Double.NEGATIVE_INFINITY, -0.0);
72+
assertTrue(query.matches(new double[] { -0.0 }, 1));
73+
assertFalse(query.matches(new double[] { 0.0 }, 1));
74+
75+
query = new DoubleScriptFieldRangeQuery(randomScript(), leafFactory, "test", Double.NEGATIVE_INFINITY, 0.0);
76+
assertTrue(query.matches(new double[] { -0.0 }, 1));
77+
assertTrue(query.matches(new double[] { 0.0 }, 1));
78+
79+
query = new DoubleScriptFieldRangeQuery(randomScript(), leafFactory, "test", -0.0, Double.POSITIVE_INFINITY);
80+
assertTrue(query.matches(new double[] { -0.0 }, 1));
81+
assertTrue(query.matches(new double[] { 0.0 }, 1));
82+
83+
query = new DoubleScriptFieldRangeQuery(randomScript(), leafFactory, "test", 0.0, Double.POSITIVE_INFINITY);
84+
assertFalse(query.matches(new double[] { -0.0 }, 1));
85+
assertTrue(query.matches(new double[] { 0.0 }, 1));
6986
}
7087

7188
@Override

x-pack/plugin/src/test/resources/rest-api-spec/test/runtime_fields/30_double.yml

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ setup:
5353
index: sensor
5454
refresh: true
5555
body: |
56+
{"index":{}}
57+
{"timestamp": 1516897304000, "temperature": 202, "voltage": 0.0, "node": "c"}
5658
{"index":{}}
5759
{"timestamp": 1516729294000, "temperature": 200, "voltage": 5.2, "node": "a"}
5860
{"index":{}}
@@ -82,13 +84,16 @@ setup:
8284

8385
---
8486
"fetch fields":
87+
- skip:
88+
version: " - 7.12.0"
89+
reason: bugfix for 0.0 value was added in 7.12.1
8590
- do:
8691
search:
8792
index: sensor
8893
body:
8994
sort: timestamp
9095
fields: [voltage_percent, voltage_percent_from_source, voltage_sqrts]
91-
- match: {hits.total.value: 6}
96+
- match: {hits.total.value: 7}
9297
- match: {hits.hits.0.fields.voltage_percent: [0.6896551724137931] }
9398
- match: {hits.hits.0.fields.voltage_percent_from_source: [0.6896551724137931] }
9499
# Scripts that scripts that emit multiple values are supported and their results are sorted
@@ -98,16 +103,20 @@ setup:
98103
- match: {hits.hits.3.fields.voltage_percent: [0.8793103448275862] }
99104
- match: {hits.hits.4.fields.voltage_percent: [1.0] }
100105
- match: {hits.hits.5.fields.voltage_percent: [0.896551724137931] }
106+
- match: {hits.hits.6.fields.voltage_percent: [0.0] }
101107

102108
---
103109
"docvalue_fields":
110+
- skip:
111+
version: " - 7.12.0"
112+
reason: bugfix for 0.0 value was added in 7.12.1
104113
- do:
105114
search:
106115
index: sensor
107116
body:
108117
sort: timestamp
109118
docvalue_fields: [voltage_percent, voltage_percent_from_source, voltage_sqrts]
110-
- match: {hits.total.value: 6}
119+
- match: {hits.total.value: 7}
111120
- match: {hits.hits.0.fields.voltage_percent: [0.6896551724137931] }
112121
- match: {hits.hits.0.fields.voltage_percent_from_source: [0.6896551724137931] }
113122
# Scripts that scripts that emit multiple values are supported and their results are sorted
@@ -117,9 +126,13 @@ setup:
117126
- match: {hits.hits.3.fields.voltage_percent: [0.8793103448275862] }
118127
- match: {hits.hits.4.fields.voltage_percent: [1.0] }
119128
- match: {hits.hits.5.fields.voltage_percent: [0.896551724137931] }
129+
- match: {hits.hits.6.fields.voltage_percent: [0.0] }
120130

121131
---
122132
"terms agg":
133+
- skip:
134+
version: " - 7.12.0"
135+
reason: bugfix for 0.0 value was added in 7.12.1
123136
- do:
124137
search:
125138
index: sensor
@@ -128,14 +141,17 @@ setup:
128141
v10:
129142
terms:
130143
field: voltage_percent
131-
- match: {hits.total.value: 6}
132-
- match: {aggregations.v10.buckets.0.key: 0.6896551724137931}
144+
- match: {hits.total.value: 7}
145+
- match: {aggregations.v10.buckets.0.key: 0.0}
133146
- match: {aggregations.v10.buckets.0.doc_count: 1}
134-
- match: {aggregations.v10.buckets.1.key: 0.7241379310344828}
147+
- match: {aggregations.v10.buckets.1.key: 0.6896551724137931}
135148
- match: {aggregations.v10.buckets.1.doc_count: 1}
136149

137150
---
138151
"range query":
152+
- skip:
153+
version: " - 7.12.0"
154+
reason: bugfix for 0.0 value was added in 7.12.1
139155
- do:
140156
search:
141157
index: sensor
@@ -144,8 +160,29 @@ setup:
144160
range:
145161
voltage_percent:
146162
lt: .7
147-
- match: {hits.total.value: 1}
148-
- match: {hits.hits.0._source.voltage: 4.0}
163+
- match: {hits.total.value: 2}
164+
- match: {hits.hits.0._source.voltage: 0.0}
165+
- match: {hits.hits.1._source.voltage: 4.0}
166+
167+
- do:
168+
search:
169+
index: sensor
170+
body:
171+
query:
172+
range:
173+
voltage_percent:
174+
lt: 0.0
175+
- match: {hits.total.value: 0}
176+
177+
- do:
178+
search:
179+
index: sensor
180+
body:
181+
query:
182+
range:
183+
voltage_percent:
184+
gt: 0.0
185+
- match: {hits.total.value: 6}
149186

150187
- do:
151188
search:

0 commit comments

Comments
 (0)