Better error message when _parent isn't an object (#21987)

If you make a mistake and specify a mapping like:
```
{
  "parent": {
    "properties": {}
  },
  "child": {
    "_parent": "parent",
    "properties": {}
  }
}
```

then the error message you get back amounts to
`Failed to parse mapping for [child]: can't cast a String to a Map`.
Since it doens't tell you *which* string can't be cast to a map you
have to dig through the stack trace to figure out what to fix. This
replaces the error message with:
```
Failed to parse mapping [child]: [_parent] must be an object containing [type]
```
so you can tell that the problem is with the `parent` field.
This commit is contained in:
Nik Everett 2016-12-09 11:33:31 -05:00 committed by GitHub
parent fc2060ba7e
commit bcef1e7452
2 changed files with 13 additions and 0 deletions

View File

@ -117,6 +117,9 @@ public class DocumentMapperParser {
MetadataFieldMapper.TypeParser typeParser = rootTypeParsers.get(fieldName);
if (typeParser != null) {
iterator.remove();
if (false == fieldNode instanceof Map) {
throw new IllegalArgumentException("[_parent] must be an object containing [type]");
}
Map<String, Object> fieldNodeMap = (Map<String, Object>) fieldNode;
docBuilder.put(typeParser.parse(fieldName, fieldNodeMap, parserContext));
fieldNodeMap.remove("type");

View File

@ -25,6 +25,7 @@ import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.test.ESSingleNodeTestCase;
import java.util.Collections;
@ -69,6 +70,15 @@ public class MetaDataMappingServiceTests extends ESSingleNodeTestCase {
assertThat(documentMapper.parentFieldMapper().active(), is(true));
}
public void testParentIsAString() throws Exception {
// Shouldn't be able the add the _parent field pointing to an already existing type, which isn't a parent type
Exception e = expectThrows(MapperParsingException.class, () -> client().admin().indices().prepareCreate("test")
.addMapping("parent", "{\"properties\":{}}")
.addMapping("child", "{\"_parent\": \"parent\",\"properties\":{}}")
.get());
assertEquals("Failed to parse mapping [child]: [_parent] must be an object containing [type]", e.getMessage());
}
public void testMappingClusterStateUpdateDoesntChangeExistingIndices() throws Exception {
final IndexService indexService = createIndex("test", client().admin().indices().prepareCreate("test").addMapping("type"));
final CompressedXContent currentMapping = indexService.mapperService().documentMapper("type").mappingSource();