Skip to content

Commit c652efe

Browse files
authored
Add utility methods to return runtime field values in doc value order (#71599) (#71604)
This adds utility methods to each type of runtime field to return the results of a document in an ordered array based on the same order that doc values are ordered in. This is useful for supporting execute api in this #71374.
1 parent f1e5650 commit c652efe

12 files changed

+219
-0
lines changed

server/src/main/java/org/elasticsearch/script/AbstractLongFieldScript.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.apache.lucene.util.ArrayUtil;
1313
import org.elasticsearch.search.lookup.SearchLookup;
1414

15+
import java.util.Arrays;
1516
import java.util.Map;
1617
import java.util.function.LongConsumer;
1718

@@ -55,6 +56,17 @@ public final long[] values() {
5556
return values;
5657
}
5758

59+
/**
60+
* Reorders the values from the last time {@link #values()} was called to
61+
* how this would appear in doc-values order. Truncates garbage values
62+
* based on {@link #count()}.
63+
*/
64+
public final long[] asDocValues() {
65+
long[] truncated = Arrays.copyOf(values, count());
66+
Arrays.sort(truncated);
67+
return truncated;
68+
}
69+
5870
/**
5971
* The number of results produced the last time {@link #runForDoc(int)} was called.
6072
*/

server/src/main/java/org/elasticsearch/script/BooleanFieldScript.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.apache.lucene.index.LeafReaderContext;
1212
import org.elasticsearch.search.lookup.SearchLookup;
1313

14+
import java.util.Arrays;
1415
import java.util.Map;
1516
import java.util.function.Consumer;
1617

@@ -68,6 +69,17 @@ public final int falses() {
6869
return falses;
6970
}
7071

72+
/**
73+
* Reorders the values from the last time {@link #runForDoc(int)} was called to
74+
* how this would appear in doc-values order.
75+
*/
76+
public final boolean[] asDocValues() {
77+
boolean[] values = new boolean[falses + trues];
78+
Arrays.fill(values, 0, falses, false);
79+
Arrays.fill(values, falses, falses + trues, true);
80+
return values;
81+
}
82+
7183
public final void emit(boolean v) {
7284
if (v) {
7385
trues++;

server/src/main/java/org/elasticsearch/script/DoubleFieldScript.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.apache.lucene.util.ArrayUtil;
1313
import org.elasticsearch.search.lookup.SearchLookup;
1414

15+
import java.util.Arrays;
1516
import java.util.Map;
1617
import java.util.function.DoubleConsumer;
1718

@@ -65,6 +66,17 @@ public final double[] values() {
6566
return values;
6667
}
6768

69+
/**
70+
* Reorders the values from the last time {@link #values()} was called to
71+
* how this would appear in doc-values order. Truncates garbage values
72+
* based on {@link #count()}.
73+
*/
74+
public final double[] asDocValues() {
75+
double[] truncated = Arrays.copyOf(values, count());
76+
Arrays.sort(truncated);
77+
return truncated;
78+
}
79+
6880
/**
6981
* The number of results produced the last time {@link #runForDoc(int)} was called.
7082
*/

server/src/main/java/org/elasticsearch/script/IpFieldScript.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.net.Inet4Address;
2020
import java.net.Inet6Address;
2121
import java.net.InetAddress;
22+
import java.util.Arrays;
2223
import java.util.Map;
2324
import java.util.function.Consumer;
2425

@@ -86,6 +87,17 @@ public final BytesRef[] values() {
8687
return values;
8788
}
8889

90+
/**
91+
* Reorders the values from the last time {@link #values()} was called to
92+
* how this would appear in doc-values order. Truncates garbage values
93+
* based on {@link #count()}.
94+
*/
95+
public final BytesRef[] asDocValues() {
96+
BytesRef[] truncated = Arrays.copyOf(values, count());
97+
Arrays.sort(truncated);
98+
return truncated;
99+
}
100+
89101
/**
90102
* The number of results produced the last time {@link #runForDoc(int)} was called.
91103
*/

server/src/main/java/org/elasticsearch/script/StringFieldScript.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.search.lookup.SearchLookup;
1313

1414
import java.util.ArrayList;
15+
import java.util.Arrays;
1516
import java.util.List;
1617
import java.util.Locale;
1718
import java.util.Map;
@@ -61,6 +62,17 @@ public final void runForDoc(int docId, Consumer<String> consumer) {
6162
resultsForDoc(docId).forEach(consumer);
6263
}
6364

65+
/**
66+
* Reorders the values from the last time {@link #resultsForDoc(int)} was called to
67+
* how this would appear in doc-values order.
68+
*/
69+
public final String[] asDocValues() {
70+
String[] values = new String[results.size()];
71+
results.toArray(values);
72+
Arrays.sort(values);
73+
return values;
74+
}
75+
6476
public final void emit(String v) {
6577
checkMaxSize(results.size());
6678
chars += v.length();

server/src/test/java/org/elasticsearch/index/mapper/BooleanFieldScriptTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.search.lookup.SearchLookup;
2020

2121
import java.io.IOException;
22+
import java.util.Collections;
2223

2324
public class BooleanFieldScriptTests extends FieldScriptTestCase<BooleanFieldScript.Factory> {
2425
public static final BooleanFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new BooleanFieldScript(
@@ -43,6 +44,27 @@ protected BooleanFieldScript.Factory dummyScript() {
4344
return DUMMY;
4445
}
4546

47+
public void testAsDocValues() {
48+
BooleanFieldScript script = new BooleanFieldScript(
49+
"test",
50+
Collections.emptyMap(),
51+
new SearchLookup(field -> null, (ft, lookup) -> null),
52+
null
53+
) {
54+
@Override
55+
public void execute() {
56+
emit(true);
57+
emit(false);
58+
emit(true);
59+
emit(true);
60+
emit(false);
61+
}
62+
};
63+
script.execute();
64+
65+
assertArrayEquals(new boolean[] {false, false, true, true, true}, script.asDocValues());
66+
}
67+
4668
public void testTooManyValues() throws IOException {
4769
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
4870
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

server/src/test/java/org/elasticsearch/index/mapper/DateFieldScriptTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import org.elasticsearch.search.lookup.SearchLookup;
2121

2222
import java.io.IOException;
23+
import java.time.ZonedDateTime;
24+
import java.util.Collections;
2325

2426
import static org.hamcrest.Matchers.equalTo;
2527

@@ -47,6 +49,26 @@ protected DateFieldScript.Factory dummyScript() {
4749
return DUMMY;
4850
}
4951

52+
public void testAsDocValues() {
53+
DateFieldScript script = new DateFieldScript(
54+
"test",
55+
Collections.emptyMap(),
56+
new SearchLookup(field -> null, (ft, lookup) -> null),
57+
DateFormatter.forPattern("YYYY-MM-DD 'T' HH:MM:SSZ"),
58+
null
59+
) {
60+
@Override
61+
public void execute() {
62+
emit(ZonedDateTime.parse("2021-01-01T00:00:00Z").toInstant().toEpochMilli());
63+
emit(ZonedDateTime.parse("1942-05-31T15:16:17Z").toInstant().toEpochMilli());
64+
emit(ZonedDateTime.parse("2035-10-13T10:54:19Z").toInstant().toEpochMilli());
65+
}
66+
};
67+
script.execute();
68+
69+
assertArrayEquals(new long[] {-870597823000L, 1609459200000L, 2075885659000L}, script.asDocValues());
70+
}
71+
5072
public void testTooManyValues() throws IOException {
5173
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
5274
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

server/src/test/java/org/elasticsearch/index/mapper/DoubleFieldScriptTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.search.lookup.SearchLookup;
2020

2121
import java.io.IOException;
22+
import java.util.Collections;
2223

2324
import static org.hamcrest.Matchers.equalTo;
2425

@@ -45,6 +46,28 @@ protected DoubleFieldScript.Factory dummyScript() {
4546
return DUMMY;
4647
}
4748

49+
public void testAsDocValues() {
50+
DoubleFieldScript script = new DoubleFieldScript(
51+
"test",
52+
Collections.emptyMap(),
53+
new SearchLookup(field -> null, (ft, lookup) -> null),
54+
null
55+
) {
56+
@Override
57+
public void execute() {
58+
emit(3.1);
59+
emit(2.29);
60+
emit(-12.47);
61+
emit(-12.46);
62+
emit(Double.MAX_VALUE);
63+
emit(0.0);
64+
}
65+
};
66+
script.execute();
67+
68+
assertArrayEquals(new double[] {-12.47, -12.46, 0.0, 2.29, 3.1, Double.MAX_VALUE}, script.asDocValues(), 0.000000001);
69+
}
70+
4871
public void testTooManyValues() throws IOException {
4972
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
5073
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

server/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldScriptTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.search.lookup.SearchLookup;
2020

2121
import java.io.IOException;
22+
import java.util.Collections;
2223

2324
import static org.hamcrest.Matchers.equalTo;
2425

@@ -45,6 +46,24 @@ protected GeoPointFieldScript.Factory dummyScript() {
4546
return DUMMY;
4647
}
4748

49+
public void testAsDocValues() {
50+
GeoPointFieldScript script = new GeoPointFieldScript(
51+
"test",
52+
Collections.emptyMap(),
53+
new SearchLookup(field -> null, (ft, lookup) -> null),
54+
null
55+
) {
56+
@Override
57+
public void execute() {
58+
emit(78.96, 12.12);
59+
emit(13.45, 56.78);
60+
}
61+
};
62+
script.execute();
63+
64+
assertArrayEquals(new long[] {1378381707499043786L, 8091971733044486384L}, script.asDocValues());
65+
}
66+
4867
public void testTooManyValues() throws IOException {
4968
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
5069
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

server/src/test/java/org/elasticsearch/index/mapper/IpFieldScriptTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.search.lookup.SearchLookup;
2020

2121
import java.io.IOException;
22+
import java.util.Collections;
2223

2324
import static org.hamcrest.Matchers.equalTo;
2425

@@ -45,6 +46,32 @@ protected IpFieldScript.Factory dummyScript() {
4546
return DUMMY;
4647
}
4748

49+
public void testAsDocValues() {
50+
IpFieldScript script = new IpFieldScript(
51+
"test",
52+
Collections.emptyMap(),
53+
new SearchLookup(field -> null, (ft, lookup) -> null),
54+
null
55+
) {
56+
@Override
57+
public void execute() {
58+
emit("192.168.0.1");
59+
emit("127.0.0.1");
60+
emit("255.255.255.255");
61+
emit("0.0.0.0");
62+
}
63+
};
64+
script.execute();
65+
66+
assertArrayEquals(new BytesRef[] {
67+
new BytesRef(new byte[] {0,0,0,0,0,0,0,0,0,0,-1,-1,0,0,0,0}),
68+
new BytesRef(new byte[] {0,0,0,0,0,0,0,0,0,0,-1,-1,127,0,0,1}),
69+
new BytesRef(new byte[] {0,0,0,0,0,0,0,0,0,0,-1,-1,-64,-88,0,1}),
70+
new BytesRef(new byte[] {0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1})},
71+
script.asDocValues()
72+
);
73+
}
74+
4875
public void testTooManyValues() throws IOException {
4976
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
5077
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

server/src/test/java/org/elasticsearch/index/mapper/LongFieldScriptTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.search.lookup.SearchLookup;
2020

2121
import java.io.IOException;
22+
import java.util.Collections;
2223

2324
import static org.hamcrest.Matchers.equalTo;
2425

@@ -45,6 +46,28 @@ protected LongFieldScript.Factory dummyScript() {
4546
return DUMMY;
4647
}
4748

49+
public void testAsDocValues() {
50+
LongFieldScript script = new LongFieldScript(
51+
"test",
52+
Collections.emptyMap(),
53+
new SearchLookup(field -> null, (ft, lookup) -> null),
54+
null
55+
) {
56+
@Override
57+
public void execute() {
58+
emit(3L);
59+
emit(1L);
60+
emit(20000000000L);
61+
emit(10L);
62+
emit(-1000L);
63+
emit(0L);
64+
}
65+
};
66+
script.execute();
67+
68+
assertArrayEquals(new long[] {-1000L, 0L, 1L, 3L, 10L, 20000000000L}, script.asDocValues());
69+
}
70+
4871
public void testTooManyValues() throws IOException {
4972
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
5073
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

server/src/test/java/org/elasticsearch/index/mapper/StringFieldScriptTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.search.lookup.SearchLookup;
2020

2121
import java.io.IOException;
22+
import java.util.Collections;
2223

2324
import static org.hamcrest.Matchers.equalTo;
2425

@@ -45,6 +46,28 @@ protected StringFieldScript.Factory dummyScript() {
4546
return DUMMY;
4647
}
4748

49+
public void testAsDocValues() {
50+
StringFieldScript script = new StringFieldScript(
51+
"test",
52+
Collections.emptyMap(),
53+
new SearchLookup(field -> null, (ft, lookup) -> null),
54+
null
55+
) {
56+
@Override
57+
public void execute() {
58+
emit("test");
59+
emit("baz was not here");
60+
emit("Data");
61+
emit("-10");
62+
emit("20");
63+
emit("9");
64+
}
65+
};
66+
script.execute();
67+
68+
assertArrayEquals(new String[] {"-10", "20", "9", "Data", "baz was not here", "test"}, script.asDocValues());
69+
}
70+
4871
public void testTooManyValues() throws IOException {
4972
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
5073
iw.addDocument(org.elasticsearch.common.collect.List.of(new StoredField("_source", new BytesRef("{}"))));

0 commit comments

Comments
 (0)