ingest: Fix rename processor change rename leaf fields into branch fields
Instead of get, set and remove we do get, remove and then set to avoid type conflicts in IngestDocument. If the set still fails we try to restore the original field in ingest document. Closes #19892
This commit is contained in:
parent
a132405642
commit
1925813e09
|
@ -166,6 +166,17 @@ public final class IngestDocument {
|
|||
* @throws IllegalArgumentException if the path is null, empty or invalid.
|
||||
*/
|
||||
public boolean hasField(String path) {
|
||||
return hasField(path, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the document contains a value for the provided path
|
||||
* @param path The path within the document in dot-notation
|
||||
* @param failOutOfRange Whether to throw an IllegalArgumentException if array is accessed outside of its range
|
||||
* @return true if the document contains a value for the field, false otherwise
|
||||
* @throws IllegalArgumentException if the path is null, empty or invalid.
|
||||
*/
|
||||
public boolean hasField(String path, boolean failOutOfRange) {
|
||||
FieldPath fieldPath = new FieldPath(path);
|
||||
Object context = fieldPath.initialContext;
|
||||
for (int i = 0; i < fieldPath.pathElements.length - 1; i++) {
|
||||
|
@ -183,7 +194,12 @@ public final class IngestDocument {
|
|||
try {
|
||||
int index = Integer.parseInt(pathElement);
|
||||
if (index < 0 || index >= list.size()) {
|
||||
return false;
|
||||
if (failOutOfRange) {
|
||||
throw new IllegalArgumentException("[" + index + "] is out of bounds for array with length [" +
|
||||
list.size() + "] as part of path [" + path +"]");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
context = list.get(index);
|
||||
} catch (NumberFormatException e) {
|
||||
|
@ -206,7 +222,16 @@ public final class IngestDocument {
|
|||
List<Object> list = (List<Object>) context;
|
||||
try {
|
||||
int index = Integer.parseInt(leafKey);
|
||||
return index >= 0 && index < list.size();
|
||||
if (index >= 0 && index < list.size()) {
|
||||
return true;
|
||||
} else {
|
||||
if (failOutOfRange) {
|
||||
throw new IllegalArgumentException("[" + index + "] is out of bounds for array with length [" +
|
||||
list.size() + "] as part of path [" + path +"]");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -239,6 +239,15 @@ public class IngestDocumentTests extends ESTestCase {
|
|||
assertFalse(ingestDocument.hasField("list.10"));
|
||||
}
|
||||
|
||||
public void testListHasFieldIndexOutOfBounds_fail() {
|
||||
assertTrue(ingestDocument.hasField("list.0", true));
|
||||
assertTrue(ingestDocument.hasField("list.1", true));
|
||||
Exception e = expectThrows(IllegalArgumentException.class, () -> ingestDocument.hasField("list.2", true));
|
||||
assertThat(e.getMessage(), equalTo("[2] is out of bounds for array with length [2] as part of path [list.2]"));
|
||||
e = expectThrows(IllegalArgumentException.class, () -> ingestDocument.hasField("list.10", true));
|
||||
assertThat(e.getMessage(), equalTo("[10] is out of bounds for array with length [2] as part of path [list.10]"));
|
||||
}
|
||||
|
||||
public void testListHasFieldIndexNotNumeric() {
|
||||
assertFalse(ingestDocument.hasField("list.test"));
|
||||
}
|
||||
|
|
|
@ -52,20 +52,24 @@ public final class RenameProcessor extends AbstractProcessor {
|
|||
|
||||
@Override
|
||||
public void execute(IngestDocument document) {
|
||||
if (document.hasField(field) == false) {
|
||||
if (document.hasField(field, true) == false) {
|
||||
throw new IllegalArgumentException("field [" + field + "] doesn't exist");
|
||||
}
|
||||
if (document.hasField(targetField)) {
|
||||
// We fail here if the target field point to an array slot that is out of range.
|
||||
// If we didn't do this then we would fail if we set the value in the target_field
|
||||
// and then on failure processors would not see that value we tried to rename as we already
|
||||
// removed it.
|
||||
if (document.hasField(targetField, true)) {
|
||||
throw new IllegalArgumentException("field [" + targetField + "] already exists");
|
||||
}
|
||||
|
||||
Object oldValue = document.getFieldValue(field, Object.class);
|
||||
document.setFieldValue(targetField, oldValue);
|
||||
Object value = document.getFieldValue(field, Object.class);
|
||||
document.removeField(field);
|
||||
try {
|
||||
document.removeField(field);
|
||||
document.setFieldValue(targetField, value);
|
||||
} catch (Exception e) {
|
||||
//remove the new field if the removal of the old one failed
|
||||
document.removeField(targetField);
|
||||
// setting the value back to the original field shouldn't as we just fetched it from that field:
|
||||
document.setFieldValue(field, value);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,4 +171,27 @@ public class RenameProcessorTests extends ESTestCase {
|
|||
assertThat(ingestDocument.getSourceAndMetadata().containsKey("new_field"), equalTo(false));
|
||||
}
|
||||
}
|
||||
|
||||
public void testRenameLeafIntoBranch() throws Exception {
|
||||
Map<String, Object> source = new HashMap<>();
|
||||
source.put("foo", "bar");
|
||||
IngestDocument ingestDocument = new IngestDocument(source, Collections.emptyMap());
|
||||
Processor processor1 = new RenameProcessor(randomAsciiOfLength(10), "foo", "foo.bar");
|
||||
processor1.execute(ingestDocument);
|
||||
assertThat(ingestDocument.getFieldValue("foo", Map.class), equalTo(Collections.singletonMap("bar", "bar")));
|
||||
assertThat(ingestDocument.getFieldValue("foo.bar", String.class), equalTo("bar"));
|
||||
|
||||
Processor processor2 = new RenameProcessor(randomAsciiOfLength(10), "foo.bar", "foo.bar.baz");
|
||||
processor2.execute(ingestDocument);
|
||||
assertThat(ingestDocument.getFieldValue("foo", Map.class), equalTo(Collections.singletonMap("bar",
|
||||
Collections.singletonMap("baz", "bar"))));
|
||||
assertThat(ingestDocument.getFieldValue("foo.bar", Map.class), equalTo(Collections.singletonMap("baz", "bar")));
|
||||
assertThat(ingestDocument.getFieldValue("foo.bar.baz", String.class), equalTo("bar"));
|
||||
|
||||
// for fun lets try to restore it (which don't allow today)
|
||||
Processor processor3 = new RenameProcessor(randomAsciiOfLength(10), "foo.bar.baz", "foo");
|
||||
Exception e = expectThrows(IllegalArgumentException.class, () -> processor3.execute(ingestDocument));
|
||||
assertThat(e.getMessage(), equalTo("field [foo] already exists"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue