Skip to content

Commit bc11a34

Browse files
authored
Add utility methods to return runtime field values in doc value order (#71599)
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 0623b03 commit bc11a34

12 files changed

+212
-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

2425
/**
@@ -78,6 +79,17 @@ public final BytesRef[] values() {
7879
return values;
7980
}
8081

82+
/**
83+
* Reorders the values from the last time {@link #values()} was called to
84+
* how this would appear in doc-values order. Truncates garbage values
85+
* based on {@link #count()}.
86+
*/
87+
public final BytesRef[] asDocValues() {
88+
BytesRef[] truncated = Arrays.copyOf(values, count());
89+
Arrays.sort(truncated);
90+
return truncated;
91+
}
92+
8193
/**
8294
* The number of results produced the last time {@link #runForDoc(int)} was called.
8395
*/

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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,27 @@ protected BooleanFieldScript.Factory dummyScript() {
4545
return DUMMY;
4646
}
4747

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

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

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

2222
import java.io.IOException;
23+
import java.time.ZonedDateTime;
2324
import java.util.List;
2425
import java.util.Map;
2526

@@ -49,6 +50,26 @@ protected DateFieldScript.Factory dummyScript() {
4950
return DUMMY;
5051
}
5152

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

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ protected DoubleFieldScript.Factory dummyScript() {
4747
return DUMMY;
4848
}
4949

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

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@ protected GeoPointFieldScript.Factory dummyScript() {
4747
return DUMMY;
4848
}
4949

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

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,32 @@ protected IpFieldScript.Factory dummyScript() {
4747
return DUMMY;
4848
}
4949

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

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ protected LongFieldScript.Factory dummyScript() {
4747
return DUMMY;
4848
}
4949

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

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,28 @@ protected StringFieldScript.Factory dummyScript() {
4747
return DUMMY;
4848
}
4949

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

0 commit comments

Comments
 (0)