Skip to content

Commit b5e8524

Browse files
authored
Fix value method on ip scripts (#61230)
Fixes `doc['ip'].value` when `ip` is a script field. It didn't work properly before because it wasn't whitelisted. We can't whitelist it easilly because it was over in a module rather than core. This fixes that by sharing more code with core that *is* whitelisted.
1 parent 3870b6f commit b5e8524

File tree

3 files changed

+39
-43
lines changed

3 files changed

+39
-43
lines changed

server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -481,25 +481,30 @@ protected void resize(int newSize) {
481481
public int size() {
482482
return count;
483483
}
484-
485484
}
486485

487-
public static final class Strings extends BinaryScriptDocValues<String> {
488-
486+
public static class Strings extends BinaryScriptDocValues<String> {
489487
public Strings(SortedBinaryDocValues in) {
490488
super(in);
491489
}
492490

493491
@Override
494-
public String get(int index) {
492+
public final String get(int index) {
495493
if (count == 0) {
496494
throw new IllegalStateException("A document doesn't have a value for a field! " +
497495
"Use doc[<field>].size()==0 to check if a document is missing a field!");
498496
}
499-
return values[index].get().utf8ToString();
497+
return bytesToString(values[index].get());
498+
}
499+
500+
/**
501+
* Convert the stored bytes to a String.
502+
*/
503+
protected String bytesToString(BytesRef bytes) {
504+
return bytes.utf8ToString();
500505
}
501506

502-
public String getValue() {
507+
public final String getValue() {
503508
return get(0);
504509
}
505510
}

x-pack/plugin/runtime-fields/src/main/java/org/elasticsearch/xpack/runtimefields/fielddata/ScriptIpFieldData.java

+10-37
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import org.apache.lucene.document.InetAddressPoint;
1010
import org.apache.lucene.index.LeafReaderContext;
11+
import org.apache.lucene.util.BytesRef;
1112
import org.elasticsearch.common.bytes.BytesArray;
1213
import org.elasticsearch.common.bytes.BytesReference;
1314
import org.elasticsearch.common.network.InetAddresses;
@@ -22,7 +23,6 @@
2223
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
2324
import org.elasticsearch.xpack.runtimefields.IpScriptFieldScript;
2425

25-
import java.io.IOException;
2626
import java.net.InetAddress;
2727

2828
public class ScriptIpFieldData extends ScriptBinaryFieldData {
@@ -54,7 +54,7 @@ public ScriptBinaryLeafFieldData loadDirect(LeafReaderContext context) throws Ex
5454
return new ScriptBinaryLeafFieldData() {
5555
@Override
5656
public ScriptDocValues<String> getScriptValues() {
57-
return new IpScriptDocValues(script);
57+
return new IpScriptDocValues(getBytesValues());
5858
}
5959

6060
@Override
@@ -70,46 +70,19 @@ public ValuesSourceType getValuesSourceType() {
7070
}
7171

7272
/**
73-
* We can't share {@link IpFieldMapper.IpFieldType.IpScriptDocValues} because it
74-
* is based on global ordinals and we don't have those.
73+
* Doc values implementation for ips. We can't share
74+
* {@link IpFieldMapper.IpFieldType.IpScriptDocValues} because it is based
75+
* on global ordinals and we don't have those.
7576
*/
76-
public static class IpScriptDocValues extends ScriptDocValues<String> {
77-
private final IpScriptFieldScript script;
78-
79-
public IpScriptDocValues(IpScriptFieldScript script) {
80-
this.script = script;
77+
public static class IpScriptDocValues extends ScriptDocValues.Strings {
78+
public IpScriptDocValues(SortedBinaryDocValues in) {
79+
super(in);
8180
}
8281

8382
@Override
84-
public void setNextDocId(int docId) throws IOException {
85-
script.runForDoc(docId);
86-
}
87-
88-
public String getValue() {
89-
if (size() == 0) {
90-
return null;
91-
}
92-
return get(0);
93-
}
94-
95-
@Override
96-
public String get(int index) {
97-
if (index >= size()) {
98-
if (size() == 0) {
99-
throw new IllegalStateException(
100-
"A document doesn't have a value for a field! "
101-
+ "Use doc[<field>].size()==0 to check if a document is missing a field!"
102-
);
103-
}
104-
throw new ArrayIndexOutOfBoundsException("There are only [" + size() + "] values.");
105-
}
106-
InetAddress addr = InetAddressPoint.decode(BytesReference.toBytes(new BytesArray(script.values()[index])));
83+
protected String bytesToString(BytesRef bytes) {
84+
InetAddress addr = InetAddressPoint.decode(BytesReference.toBytes(new BytesArray(bytes)));
10785
return InetAddresses.toAddrString(addr);
10886
}
109-
110-
@Override
111-
public int size() {
112-
return script.count();
113-
}
11487
}
11588
}

x-pack/plugin/src/test/resources/rest-api-spec/test/runtime_fields/50_ip.yml

+18
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,24 @@ setup:
111111
- match: {aggregations.ip.buckets.1.key: 26.1.0.0}
112112
- match: {aggregations.ip.buckets.1.doc_count: 1}
113113

114+
---
115+
"use in scripts":
116+
- do:
117+
search:
118+
index: http_logs
119+
body:
120+
aggs:
121+
ip:
122+
terms:
123+
script:
124+
String v = doc['ip'].value;
125+
return v.substring(0, v.indexOf('.'));
126+
- match: {hits.total.value: 6}
127+
- match: {aggregations.ip.buckets.0.key: '247'}
128+
- match: {aggregations.ip.buckets.0.doc_count: 2}
129+
- match: {aggregations.ip.buckets.1.key: '232'}
130+
- match: {aggregations.ip.buckets.1.doc_count: 1}
131+
114132
---
115133
"term query":
116134
- do:

0 commit comments

Comments
 (0)