Skip to content

Commit f200c48

Browse files
committed
Field API path syntax support in IngestDocument
1 parent 6a9d765 commit f200c48

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

server/src/main/java/org/elasticsearch/ingest/IngestDocument.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.common.util.Maps;
1515
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
1616
import org.elasticsearch.common.util.set.Sets;
17+
import org.elasticsearch.core.Nullable;
1718
import org.elasticsearch.core.UpdateForV10;
1819
import org.elasticsearch.index.VersionType;
1920
import org.elasticsearch.index.mapper.IdFieldMapper;
@@ -24,6 +25,7 @@
2425
import org.elasticsearch.script.CtxMap;
2526
import org.elasticsearch.script.ScriptService;
2627
import org.elasticsearch.script.TemplateScript;
28+
import org.elasticsearch.script.field.WriteField;
2729

2830
import java.time.ZoneOffset;
2931
import java.time.ZonedDateTime;
@@ -192,6 +194,17 @@ public <T> T getFieldValue(String path, Class<T> clazz) {
192194
*/
193195
public <T> T getFieldValue(String path, Class<T> clazz, boolean ignoreMissing) {
194196
final FieldPath fieldPath = FieldPath.of(path);
197+
WriteField writeField = getWriteField(path);
198+
if (writeField != null) {
199+
if (writeField.exists() == false) {
200+
if (ignoreMissing == false) {
201+
throw new IllegalArgumentException("no field found for path " + path);
202+
} else {
203+
return null;
204+
}
205+
}
206+
return cast(path, writeField.get(null), clazz);
207+
}
195208
Object context = fieldPath.initialContext(this);
196209
ResolveResult result = resolve(fieldPath.pathElements, fieldPath.pathElements.length, path, context);
197210
if (result.wasSuccessful) {
@@ -257,6 +270,10 @@ public boolean hasField(String path) {
257270
* @throws IllegalArgumentException if the path is null, empty or invalid.
258271
*/
259272
public boolean hasField(String path, boolean failOutOfRange) {
273+
WriteField writeField = getWriteField(path);
274+
if (writeField != null) {
275+
return writeField.exists();
276+
}
260277
final FieldPath fieldPath = FieldPath.of(path);
261278
Object context = fieldPath.initialContext(this);
262279
for (int i = 0; i < fieldPath.pathElements.length - 1; i++) {
@@ -325,6 +342,14 @@ public void removeField(String path) {
325342
removeField(path, false);
326343
}
327344

345+
@Nullable
346+
private WriteField getWriteField(String path) {
347+
if ((path.startsWith("$('") && path.endsWith("')") ) || (path.startsWith("$(\"") && path.endsWith("\")"))) {
348+
return new WriteField(path.substring(3, path.length() - 2), this::getCtxMap);
349+
}
350+
return null;
351+
}
352+
328353
/**
329354
* Removes the field identified by the provided path.
330355
*
@@ -333,6 +358,14 @@ public void removeField(String path) {
333358
* @throws IllegalArgumentException if the path is null, empty, or invalid; or if the field doesn't exist (and ignoreMissing is false).
334359
*/
335360
public void removeField(String path, boolean ignoreMissing) {
361+
WriteField writeField = getWriteField(path);
362+
if (writeField != null) {
363+
if (ignoreMissing == false && writeField.exists() == false) {
364+
throw new IllegalArgumentException("no field found for path " + path);
365+
}
366+
writeField.remove();
367+
return;
368+
}
336369
final FieldPath fieldPath = FieldPath.of(path);
337370
Object context = fieldPath.initialContext(this);
338371
ResolveResult result = resolve(fieldPath.pathElements, fieldPath.pathElements.length - 1, path, context);
@@ -548,6 +581,15 @@ public void setFieldValue(String path, Object value, boolean ignoreEmptyValue) {
548581
}
549582

550583
private void setFieldValue(String path, Object value, boolean append, boolean allowDuplicates) {
584+
WriteField writeField = getWriteField(path);
585+
if (writeField != null) {
586+
if (append && writeField.exists()) {
587+
writeField.set(appendValues(writeField.get(null), value, allowDuplicates));
588+
} else {
589+
writeField.set(value);
590+
}
591+
return;
592+
}
551593
final FieldPath fieldPath = FieldPath.of(path);
552594
Object context = fieldPath.initialContext(this);
553595
for (int i = 0; i < fieldPath.pathElements.length - 1; i++) {

server/src/test/java/org/elasticsearch/ingest/IngestDocumentTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,4 +1227,31 @@ public void testSourceHashMapIsNotCopied() {
12271227
assertThat(document2.getCtxMap().getMetadata(), not(sameInstance(document1.getCtxMap().getMetadata())));
12281228
}
12291229
}
1230+
1231+
public void testFieldApiPathSyntax() {
1232+
IngestDocument doc = RandomDocumentPicks.randomIngestDocument(random(), new HashMap<>());
1233+
1234+
doc.setFieldValue("$('foo.bar.baz')", "qux");
1235+
assertThat(doc.getFieldValue("foo.bar.baz", String.class), equalTo("qux"));
1236+
assertThat(doc.getFieldValue("$(\"foo.bar.baz\")", String.class), equalTo("qux"));
1237+
1238+
doc.appendFieldValue("$('foo.bar.baz')", "quux");
1239+
assertThat(doc.getFieldValue("foo.bar.baz", List.class), equalTo(List.of("qux", "quux")));
1240+
doc.appendFieldValue("$('foo.bar.baz')", "quux", false);
1241+
assertThat(doc.getFieldValue("foo.bar.baz", List.class), equalTo(List.of("qux", "quux")));
1242+
1243+
IllegalArgumentException e;
1244+
e = expectThrows(IllegalArgumentException.class, () -> document.getFieldValue("$('foo.missing')", String.class, false));
1245+
assertThat(e.getMessage(), is("no field found for path $('foo.missing')"));
1246+
1247+
doc.getSource().put("host.name", "localhost");
1248+
assertTrue(doc.hasField("$('foo.bar.baz')"));
1249+
assertThat(doc.getFieldValue("$('host.name')", String.class), equalTo("localhost"));
1250+
1251+
doc.removeField("$('foo.bar.baz')");
1252+
assertFalse(doc.hasField("$('foo.bar.baz')"));
1253+
// when removing the same field again, it should throw an exception
1254+
e = expectThrows(IllegalArgumentException.class, () -> doc.removeField("$('foo.bar.baz')"));
1255+
assertThat(e.getMessage(), is("no field found for path $('foo.bar.baz')"));
1256+
}
12301257
}

0 commit comments

Comments
 (0)