Fix not Recognizing Disabled Object Mapper (#39862)
* Fixes not finding disabled object mapper when using dotted field name notation * Closes #39456
This commit is contained in:
parent
52b0b9cb55
commit
e2b60c7141
|
@ -83,6 +83,20 @@ final class DocumentParser {
|
||||||
return parsedDocument(source, context, createDynamicUpdate(mapping, docMapper, context.getDynamicMappers()));
|
return parsedDocument(source, context, createDynamicUpdate(mapping, docMapper, context.getDynamicMappers()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean containsDisabledObjectMapper(ObjectMapper objectMapper, String[] subfields) {
|
||||||
|
for (int i = 0; i < subfields.length - 1; ++i) {
|
||||||
|
Mapper mapper = objectMapper.getMapper(subfields[i]);
|
||||||
|
if (mapper instanceof ObjectMapper == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
objectMapper = (ObjectMapper) mapper;
|
||||||
|
if (objectMapper.isEnabled() == false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static void internalParseDocument(Mapping mapping, MetadataFieldMapper[] metadataFieldsMappers,
|
private static void internalParseDocument(Mapping mapping, MetadataFieldMapper[] metadataFieldsMappers,
|
||||||
ParseContext.InternalParseContext context, XContentParser parser) throws IOException {
|
ParseContext.InternalParseContext context, XContentParser parser) throws IOException {
|
||||||
final boolean emptyDoc = isEmptyDoc(mapping, parser);
|
final boolean emptyDoc = isEmptyDoc(mapping, parser);
|
||||||
|
@ -387,24 +401,30 @@ final class DocumentParser {
|
||||||
|
|
||||||
private static void innerParseObject(ParseContext context, ObjectMapper mapper, XContentParser parser,
|
private static void innerParseObject(ParseContext context, ObjectMapper mapper, XContentParser parser,
|
||||||
String currentFieldName, XContentParser.Token token) throws IOException {
|
String currentFieldName, XContentParser.Token token) throws IOException {
|
||||||
|
assert token == XContentParser.Token.FIELD_NAME || token == XContentParser.Token.END_OBJECT;
|
||||||
|
String[] paths = null;
|
||||||
while (token != XContentParser.Token.END_OBJECT) {
|
while (token != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.START_OBJECT) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
parseObject(context, mapper, currentFieldName);
|
|
||||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
|
||||||
parseArray(context, mapper, currentFieldName);
|
|
||||||
} else if (token == XContentParser.Token.FIELD_NAME) {
|
|
||||||
currentFieldName = parser.currentName();
|
currentFieldName = parser.currentName();
|
||||||
|
paths = splitAndValidatePath(currentFieldName);
|
||||||
if (MapperService.isMetadataField(context.path().pathAsText(currentFieldName))) {
|
if (MapperService.isMetadataField(context.path().pathAsText(currentFieldName))) {
|
||||||
throw new MapperParsingException("Field [" + currentFieldName + "] is a metadata field and cannot be added inside"
|
throw new MapperParsingException("Field [" + currentFieldName + "] is a metadata field and cannot be added inside"
|
||||||
+ " a document. Use the index API request parameters.");
|
+ " a document. Use the index API request parameters.");
|
||||||
|
} else if (containsDisabledObjectMapper(mapper, paths)) {
|
||||||
|
parser.nextToken();
|
||||||
|
parser.skipChildren();
|
||||||
}
|
}
|
||||||
|
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||||
|
parseObject(context, mapper, currentFieldName, paths);
|
||||||
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||||
|
parseArray(context, mapper, currentFieldName, paths);
|
||||||
} else if (token == XContentParser.Token.VALUE_NULL) {
|
} else if (token == XContentParser.Token.VALUE_NULL) {
|
||||||
parseNullValue(context, mapper, currentFieldName);
|
parseNullValue(context, mapper, currentFieldName, paths);
|
||||||
} else if (token == null) {
|
} else if (token == null) {
|
||||||
throw new MapperParsingException("object mapping for [" + mapper.name() + "] tried to parse field [" + currentFieldName
|
throw new MapperParsingException("object mapping for [" + mapper.name() + "] tried to parse field [" + currentFieldName
|
||||||
+ "] as object, but got EOF, has a concrete value been provided to it?");
|
+ "] as object, but got EOF, has a concrete value been provided to it?");
|
||||||
} else if (token.isValue()) {
|
} else if (token.isValue()) {
|
||||||
parseValue(context, mapper, currentFieldName, token);
|
parseValue(context, mapper, currentFieldName, token, paths);
|
||||||
}
|
}
|
||||||
token = parser.nextToken();
|
token = parser.nextToken();
|
||||||
}
|
}
|
||||||
|
@ -475,10 +495,10 @@ final class DocumentParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseObject(final ParseContext context, ObjectMapper mapper, String currentFieldName) throws IOException {
|
private static void parseObject(final ParseContext context, ObjectMapper mapper, String currentFieldName,
|
||||||
|
String[] paths) throws IOException {
|
||||||
assert currentFieldName != null;
|
assert currentFieldName != null;
|
||||||
|
|
||||||
final String[] paths = splitAndValidatePath(currentFieldName);
|
|
||||||
Mapper objectMapper = getMapper(mapper, currentFieldName, paths);
|
Mapper objectMapper = getMapper(mapper, currentFieldName, paths);
|
||||||
if (objectMapper != null) {
|
if (objectMapper != null) {
|
||||||
context.path().add(currentFieldName);
|
context.path().add(currentFieldName);
|
||||||
|
@ -512,10 +532,10 @@ final class DocumentParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseArray(ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
|
private static void parseArray(ParseContext context, ObjectMapper parentMapper, String lastFieldName,
|
||||||
|
String[] paths) throws IOException {
|
||||||
String arrayFieldName = lastFieldName;
|
String arrayFieldName = lastFieldName;
|
||||||
|
|
||||||
final String[] paths = splitAndValidatePath(arrayFieldName);
|
|
||||||
Mapper mapper = getMapper(parentMapper, lastFieldName, paths);
|
Mapper mapper = getMapper(parentMapper, lastFieldName, paths);
|
||||||
if (mapper != null) {
|
if (mapper != null) {
|
||||||
// There is a concrete mapper for this field already. Need to check if the mapper
|
// There is a concrete mapper for this field already. Need to check if the mapper
|
||||||
|
@ -562,35 +582,33 @@ final class DocumentParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseNonDynamicArray(ParseContext context, ObjectMapper mapper,
|
private static void parseNonDynamicArray(ParseContext context, ObjectMapper mapper,
|
||||||
String lastFieldName, String arrayFieldName) throws IOException {
|
final String lastFieldName, String arrayFieldName) throws IOException {
|
||||||
XContentParser parser = context.parser();
|
XContentParser parser = context.parser();
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
|
final String[] paths = splitAndValidatePath(lastFieldName);
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
if (token == XContentParser.Token.START_OBJECT) {
|
if (token == XContentParser.Token.START_OBJECT) {
|
||||||
parseObject(context, mapper, lastFieldName);
|
parseObject(context, mapper, lastFieldName, paths);
|
||||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||||
parseArray(context, mapper, lastFieldName);
|
parseArray(context, mapper, lastFieldName, paths);
|
||||||
} else if (token == XContentParser.Token.FIELD_NAME) {
|
|
||||||
lastFieldName = parser.currentName();
|
|
||||||
} else if (token == XContentParser.Token.VALUE_NULL) {
|
} else if (token == XContentParser.Token.VALUE_NULL) {
|
||||||
parseNullValue(context, mapper, lastFieldName);
|
parseNullValue(context, mapper, lastFieldName, paths);
|
||||||
} else if (token == null) {
|
} else if (token == null) {
|
||||||
throw new MapperParsingException("object mapping for [" + mapper.name() + "] with array for [" + arrayFieldName
|
throw new MapperParsingException("object mapping for [" + mapper.name() + "] with array for [" + arrayFieldName
|
||||||
+ "] tried to parse as array, but got EOF, is there a mismatch in types for the same field?");
|
+ "] tried to parse as array, but got EOF, is there a mismatch in types for the same field?");
|
||||||
} else {
|
} else {
|
||||||
parseValue(context, mapper, lastFieldName, token);
|
assert token.isValue();
|
||||||
|
parseValue(context, mapper, lastFieldName, token, paths);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseValue(final ParseContext context, ObjectMapper parentMapper,
|
private static void parseValue(final ParseContext context, ObjectMapper parentMapper,
|
||||||
String currentFieldName, XContentParser.Token token) throws IOException {
|
String currentFieldName, XContentParser.Token token, String[] paths) throws IOException {
|
||||||
if (currentFieldName == null) {
|
if (currentFieldName == null) {
|
||||||
throw new MapperParsingException("object mapping [" + parentMapper.name() + "] trying to serialize a value with"
|
throw new MapperParsingException("object mapping [" + parentMapper.name() + "] trying to serialize a value with"
|
||||||
+ " no field associated with it, current value [" + context.parser().textOrNull() + "]");
|
+ " no field associated with it, current value [" + context.parser().textOrNull() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
final String[] paths = splitAndValidatePath(currentFieldName);
|
|
||||||
Mapper mapper = getMapper(parentMapper, currentFieldName, paths);
|
Mapper mapper = getMapper(parentMapper, currentFieldName, paths);
|
||||||
if (mapper != null) {
|
if (mapper != null) {
|
||||||
parseObjectOrField(context, mapper);
|
parseObjectOrField(context, mapper);
|
||||||
|
@ -605,9 +623,10 @@ final class DocumentParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseNullValue(ParseContext context, ObjectMapper parentMapper, String lastFieldName) throws IOException {
|
private static void parseNullValue(ParseContext context, ObjectMapper parentMapper, String lastFieldName,
|
||||||
|
String[] paths) throws IOException {
|
||||||
// we can only handle null values if we have mappings for them
|
// we can only handle null values if we have mappings for them
|
||||||
Mapper mapper = getMapper(parentMapper, lastFieldName, splitAndValidatePath(lastFieldName));
|
Mapper mapper = getMapper(parentMapper, lastFieldName, paths);
|
||||||
if (mapper != null) {
|
if (mapper != null) {
|
||||||
// TODO: passing null to an object seems bogus?
|
// TODO: passing null to an object seems bogus?
|
||||||
parseObjectOrField(context, mapper);
|
parseObjectOrField(context, mapper);
|
||||||
|
|
|
@ -79,6 +79,56 @@ public class DocumentParserTests extends ESSingleNodeTestCase {
|
||||||
assertNotNull(doc.rootDoc().getField(IdFieldMapper.NAME));
|
assertNotNull(doc.rootDoc().getField(IdFieldMapper.NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDotsWithFieldDisabled() throws IOException {
|
||||||
|
DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser();
|
||||||
|
String mapping = Strings.toString(jsonBuilder().startObject().startObject("type").startObject("properties")
|
||||||
|
.startObject("foo").field("enabled", false).endObject()
|
||||||
|
.endObject().endObject().endObject());
|
||||||
|
DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping));
|
||||||
|
{
|
||||||
|
BytesReference bytes = BytesReference.bytes(jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("foo.bar", 111)
|
||||||
|
.endObject());
|
||||||
|
ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON));
|
||||||
|
assertNull(doc.rootDoc().getField("foo"));
|
||||||
|
assertNull(doc.rootDoc().getField("bar"));
|
||||||
|
assertNull(doc.rootDoc().getField("foo.bar"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BytesReference bytes = BytesReference.bytes(jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("foo.bar", new int[]{1, 2, 3})
|
||||||
|
.endObject());
|
||||||
|
ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON));
|
||||||
|
assertNull(doc.rootDoc().getField("foo"));
|
||||||
|
assertNull(doc.rootDoc().getField("bar"));
|
||||||
|
assertNull(doc.rootDoc().getField("foo.bar"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BytesReference bytes = BytesReference.bytes(jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("foo.bar", Collections.singletonMap("key", "value"))
|
||||||
|
.endObject());
|
||||||
|
ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON));
|
||||||
|
assertNull(doc.rootDoc().getField("foo"));
|
||||||
|
assertNull(doc.rootDoc().getField("bar"));
|
||||||
|
assertNull(doc.rootDoc().getField("foo.bar"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BytesReference bytes = BytesReference.bytes(jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("foo.bar", "string value")
|
||||||
|
.field("blub", 222)
|
||||||
|
.endObject());
|
||||||
|
ParsedDocument doc = mapper.parse(new SourceToParse("test", "type", "1", bytes, XContentType.JSON));
|
||||||
|
assertNull(doc.rootDoc().getField("foo"));
|
||||||
|
assertNull(doc.rootDoc().getField("bar"));
|
||||||
|
assertNull(doc.rootDoc().getField("foo.bar"));
|
||||||
|
assertNotNull(doc.rootDoc().getField("blub"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testDotsWithExistingMapper() throws Exception {
|
public void testDotsWithExistingMapper() throws Exception {
|
||||||
DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser();
|
DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser();
|
||||||
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties")
|
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties")
|
||||||
|
|
Loading…
Reference in New Issue