Allow terms aggregations on pure boolean scripts. (#22201)
The way aggregations on scripts work is by hiding scripts behind the same API that we use for regular fields. However, there is no native support for boolean fields, those need to be exposed as integers, with `0` standing for `false` and `1` for true. Relates #20941
This commit is contained in:
parent
0e9186e137
commit
3b3f9216db
|
@ -50,15 +50,10 @@ public class ScriptLongValues extends SortingNumericDocValues implements ScorerA
|
|||
resize(0);
|
||||
}
|
||||
|
||||
else if (value instanceof Number) {
|
||||
resize(1);
|
||||
values[0] = ((Number) value).longValue();
|
||||
}
|
||||
|
||||
else if (value.getClass().isArray()) {
|
||||
resize(Array.getLength(value));
|
||||
for (int i = 0; i < count(); ++i) {
|
||||
values[i] = ((Number) Array.get(value, i)).longValue();
|
||||
values[i] = toLongValue(Array.get(value, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,18 +61,33 @@ public class ScriptLongValues extends SortingNumericDocValues implements ScorerA
|
|||
resize(((Collection<?>) value).size());
|
||||
int i = 0;
|
||||
for (Iterator<?> it = ((Collection<?>) value).iterator(); it.hasNext(); ++i) {
|
||||
values[i] = ((Number) it.next()).longValue();
|
||||
values[i] = toLongValue(it.next());
|
||||
}
|
||||
assert i == count();
|
||||
}
|
||||
|
||||
else {
|
||||
throw new AggregationExecutionException("Unsupported script value [" + value + "]");
|
||||
resize(1);
|
||||
values[0] = toLongValue(value);
|
||||
}
|
||||
|
||||
sort();
|
||||
}
|
||||
|
||||
private static long toLongValue(Object o) {
|
||||
if (o instanceof Number) {
|
||||
return ((Number) o).longValue();
|
||||
} else if (o instanceof Boolean) {
|
||||
// We do expose boolean fields as boolean in scripts, however aggregations still expect
|
||||
// that scripts return the same internal representation as regular fields, so boolean
|
||||
// values in scripts need to be converted to a number, and the value formatter will
|
||||
// make sure of using true/false in the key_as_string field
|
||||
return ((Boolean) o).booleanValue() ? 1L : 0L;
|
||||
} else {
|
||||
throw new AggregationExecutionException("Unsupported script value [" + o + "], expected a number");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) {
|
||||
script.setScorer(scorer);
|
||||
|
|
|
@ -108,6 +108,27 @@ public class ScriptValuesTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testBooleans() {
|
||||
final Object[][] values = new Boolean[randomInt(10)][];
|
||||
for (int i = 0; i < values.length; ++i) {
|
||||
Boolean[] booleans = new Boolean[randomInt(8)];
|
||||
for (int j = 0; j < booleans.length; ++j) {
|
||||
booleans[j] = randomBoolean();
|
||||
}
|
||||
Arrays.sort(booleans);
|
||||
values[i] = booleans;
|
||||
}
|
||||
FakeSearchScript script = new FakeSearchScript(values);
|
||||
ScriptLongValues scriptValues = new ScriptLongValues(script);
|
||||
for (int i = 0; i < values.length; ++i) {
|
||||
scriptValues.setDocument(i);
|
||||
assertEquals(values[i].length, scriptValues.count());
|
||||
for (int j = 0; j < values[i].length; ++j) {
|
||||
assertEquals(values[i][j], scriptValues.valueAt(j) == 1L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testDoubles() {
|
||||
final Object[][] values = new Double[randomInt(10)][];
|
||||
for (int i = 0; i < values.length; ++i) {
|
||||
|
|
Loading…
Reference in New Issue