Browse Source

Merge pull request #19765 from rjernst/metadata_mapper_dup

Mappings: Fix detection of metadata fields in documents
Ryan Ernst 9 năm trước cách đây
mục cha
commit
c3a5e4fa48

+ 4 - 5
core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java

@@ -340,17 +340,13 @@ final class DocumentParser {
             return;
         }
         XContentParser parser = context.parser();
-
-        String currentFieldName = parser.currentName();
-        if (atRoot && MapperService.isMetadataField(currentFieldName)) {
-            throw new MapperParsingException("Field [" + currentFieldName + "] is a metadata field and cannot be added inside a document. Use the index API request parameters.");
-        }
         XContentParser.Token token = parser.currentToken();
         if (token == XContentParser.Token.VALUE_NULL) {
             // the object is null ("obj1" : null), simply bail
             return;
         }
 
+        String currentFieldName = parser.currentName();
         if (token.isValue()) {
             throw new MapperParsingException("object mapping for [" + mapper.name() + "] tried to parse field [" + currentFieldName + "] as object, but found a concrete value");
         }
@@ -384,6 +380,9 @@ final class DocumentParser {
                 parseArray(context, mapper, currentFieldName);
             } else if (token == XContentParser.Token.FIELD_NAME) {
                 currentFieldName = parser.currentName();
+                if (MapperService.isMetadataField(context.path().pathAsText(currentFieldName))) {
+                    throw new MapperParsingException("Field [" + currentFieldName + "] is a metadata field and cannot be added inside a document. Use the index API request parameters.");
+                }
             } else if (token == XContentParser.Token.VALUE_NULL) {
                 parseNullValue(context, mapper, currentFieldName);
             } else if (token == null) {

+ 15 - 0
core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java

@@ -862,4 +862,19 @@ public class DocumentParserTests extends ESSingleNodeTestCase {
                 () -> mapper.parse("test", "type", "1", bytes));
         assertEquals("mapping set to strict, dynamic introduction of [foo] within [type] is not allowed", exception.getMessage());
     }
+
+    public void testDocumentContainsMetadataField() throws Exception {
+        DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser();
+        String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string();
+        DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping));
+
+        BytesReference bytes = XContentFactory.jsonBuilder().startObject().field("_ttl", 0).endObject().bytes();
+        MapperParsingException e = expectThrows(MapperParsingException.class, () ->
+            mapper.parse("test", "type", "1", bytes)
+        );
+        assertTrue(e.getMessage(), e.getMessage().contains("cannot be added inside a document"));
+
+        BytesReference bytes2 = XContentFactory.jsonBuilder().startObject().field("foo._ttl", 0).endObject().bytes();
+        mapper.parse("test", "type", "1", bytes2); // parses without error
+    }
 }