Просмотр исходного кода

FieldTypeLookup to support dynamic runtime fields (#73519)

We recently streamlined support for dynamic field lookups in FieldTypeLookup. That is now used by the flattened field mapper. We would also like to use it for runtime fields, hence this commit adds support for dynamic runtime fields.

This will be useful to support emitting multiple fields from a single runtime field script, as the sub-fields will be dynamically emitted.
Luca Cavanna 4 лет назад
Родитель
Сommit
313d832283

+ 8 - 2
server/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java

@@ -79,9 +79,15 @@ final class FieldTypeLookup {
         }
 
         for (RuntimeField runtimeField : runtimeFields) {
+            if (runtimeField instanceof DynamicFieldType) {
+                dynamicFieldTypes.put(runtimeField.name(), (DynamicFieldType) runtimeField);
+            }
             MappedFieldType runtimeFieldType = runtimeField.asMappedFieldType();
-            //this will override concrete fields with runtime fields that have the same name
-            fullNameToFieldType.put(runtimeFieldType.name(), runtimeFieldType);
+            assert runtimeFieldType != null || runtimeField instanceof DynamicFieldType;
+            if (runtimeFieldType != null) {
+                //this will override concrete fields with runtime fields that have the same name
+                fullNameToFieldType.put(runtimeFieldType.name(), runtimeFieldType);
+            }
         }
     }
 

+ 18 - 0
server/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java

@@ -187,6 +187,24 @@ public class FieldTypeLookupTests extends ESTestCase {
         }
     }
 
+    public void testDynamicRuntimeFields() {
+        FieldTypeLookup fieldTypeLookup = new FieldTypeLookup(emptyList(), emptyList(),
+            Collections.singletonList(new TestDynamicRuntimeField("test")));
+
+        assertNull(fieldTypeLookup.get("test"));
+        assertEquals(0, fieldTypeLookup.getMatchingFieldTypes("test").size());
+        assertEquals(0, fieldTypeLookup.getMatchingFieldNames("test").size());
+
+        String fieldName = "test." + randomAlphaOfLengthBetween(3, 6);
+        assertEquals(KeywordFieldMapper.CONTENT_TYPE, fieldTypeLookup.get(fieldName).typeName());
+        Collection<MappedFieldType> matchingFieldTypes = fieldTypeLookup.getMatchingFieldTypes(fieldName);
+        assertEquals(1, matchingFieldTypes.size());
+        assertEquals(KeywordFieldMapper.CONTENT_TYPE, matchingFieldTypes.iterator().next().typeName());
+        Set<String> matchingFieldNames = fieldTypeLookup.getMatchingFieldNames(fieldName);
+        assertEquals(1, matchingFieldTypes.size());
+        assertEquals(fieldName, matchingFieldNames.iterator().next());
+    }
+
     public void testFlattenedLookup() {
         String fieldName = "object1.object2.field";
         FlattenedFieldMapper mapper = createFlattenedMapper(fieldName);

+ 45 - 0
server/src/test/java/org/elasticsearch/index/mapper/TestDynamicRuntimeField.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.index.mapper;
+
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+public class TestDynamicRuntimeField implements RuntimeField, DynamicFieldType {
+
+    private final String name;
+
+    public TestDynamicRuntimeField(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public void doXContentBody(XContentBuilder builder, Params params) {
+
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public String typeName() {
+        return "dynamic";
+    }
+
+    @Override
+    public MappedFieldType asMappedFieldType() {
+        return null;
+    }
+
+    @Override
+    public MappedFieldType getChildFieldType(String path) {
+        return new KeywordScriptFieldType(name + "." + path);
+    }
+}