ソースを参照

ingest: dot_expander_processor prevent null add/append to source document (#35106)

* don't allow null values to be added or appended to the 
source document if the field does not exist.
Jake Landis 7 年 前
コミット
9150a93b1c

+ 20 - 18
modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/DotExpanderProcessor.java

@@ -52,28 +52,30 @@ public final class DotExpanderProcessor extends AbstractProcessor {
             map = ingestDocument.getSourceAndMetadata();
         }
 
-        if (ingestDocument.hasField(path)) {
-            Object value = map.remove(field);
-            ingestDocument.appendFieldValue(path, value);
-        } else {
-            // check whether we actually can expand the field in question into an object field.
-            // part of the path may already exist and if part of it would be a value field (string, integer etc.)
-            // then we can't override it with an object field and we should fail with a good reason.
-            // IngestDocument#setFieldValue(...) would fail too, but the error isn't very understandable
-            for (int index = path.indexOf('.'); index != -1; index = path.indexOf('.', index + 1)) {
-                String partialPath = path.substring(0, index);
-                if (ingestDocument.hasField(partialPath)) {
-                    Object val = ingestDocument.getFieldValue(partialPath, Object.class);
-                    if ((val instanceof Map) == false) {
-                        throw new IllegalArgumentException("cannot expend [" + path + "], because [" + partialPath +
+        if (map.containsKey(field)) {
+            if (ingestDocument.hasField(path)) {
+                Object value = map.remove(field);
+                ingestDocument.appendFieldValue(path, value);
+            } else {
+                // check whether we actually can expand the field in question into an object field.
+                // part of the path may already exist and if part of it would be a value field (string, integer etc.)
+                // then we can't override it with an object field and we should fail with a good reason.
+                // IngestDocument#setFieldValue(...) would fail too, but the error isn't very understandable
+                for (int index = path.indexOf('.'); index != -1; index = path.indexOf('.', index + 1)) {
+                    String partialPath = path.substring(0, index);
+                    if (ingestDocument.hasField(partialPath)) {
+                        Object val = ingestDocument.getFieldValue(partialPath, Object.class);
+                        if ((val instanceof Map) == false) {
+                            throw new IllegalArgumentException("cannot expend [" + path + "], because [" + partialPath +
                                 "] is not an object field, but a value field");
+                        }
+                    } else {
+                        break;
                     }
-                } else {
-                    break;
                 }
+                Object value = map.remove(field);
+                ingestDocument.setFieldValue(path, value);
             }
-            Object value = map.remove(field);
-            ingestDocument.setFieldValue(path, value);
         }
         return ingestDocument;
     }

+ 34 - 0
modules/ingest-common/src/test/java/org/elasticsearch/ingest/common/DotExpanderProcessorTests.java

@@ -143,4 +143,38 @@ public class DotExpanderProcessorTests extends ESTestCase {
         assertThat(document.getFieldValue("field.foo.bar.baz", String.class), equalTo("value"));
     }
 
+
+    public void testEscapeFields_doNothingIfFieldNotInSourceDoc() throws Exception {
+        //asking to expand a (literal) field that is not present in the source document
+        Map<String, Object> source = new HashMap<>();
+        source.put("foo.bar", "baz1");
+        IngestDocument document = new IngestDocument(source, Collections.emptyMap());
+        //abc.def does not exist in source, so don't mutate document
+        DotExpanderProcessor processor = new DotExpanderProcessor("_tag", null, "abc.def");
+        processor.execute(document);
+        //hasField returns false since it requires the expanded form, which is not expanded since we did not ask for it to be
+        assertFalse(document.hasField("foo.bar"));
+        //nothing has changed
+        assertEquals(document.getSourceAndMetadata().get("foo.bar"), "baz1");
+        //abc.def is not found anywhere
+        assertFalse(document.hasField("abc.def"));
+        assertFalse(document.getSourceAndMetadata().containsKey("abc"));
+        assertFalse(document.getSourceAndMetadata().containsKey("abc.def"));
+
+        //asking to expand a (literal) field that does not exist, but the nested field does exist
+        source = new HashMap<>();
+        Map<String, Object> inner = new HashMap<>();
+        inner.put("bar", "baz1");
+        source.put("foo", inner);
+        document = new IngestDocument(source, Collections.emptyMap());
+        //foo.bar, the literal value (as opposed to nested value) does not exist in source, so don't mutate document
+        processor = new DotExpanderProcessor("_tag", null, "foo.bar");
+        processor.execute(document);
+        //hasField returns true because the nested/expanded form exists in the source document
+        assertTrue(document.hasField("foo.bar"));
+        //nothing changed
+        assertThat(document.getFieldValue("foo", Map.class).size(), equalTo(1));
+        assertThat(document.getFieldValue("foo.bar", String.class), equalTo("baz1"));
+    }
+
 }