Fix dynamic mapping update generation. (#27467)

When a field is not mapped, Elasticsearch tries to generate a mapping update
from the parsed document. Some documents can introduce corner-cases, for
instance in the event of a multi-valued field whose values would be mapped to
different field types if they were supplied on their own, see for instance:

```
PUT index/doc/1
{
  "foo": ["2017-11-10T02:00:01.247Z","bar"]
}
```

In that case, dynamic mappings want to map the first value as a `date` field
and the second one as a `text` field. This currently throws an exception,
which is expected, but the wrong one since it throws a `class_cast_exception`
(which triggers a HTTP 5xx code) when it should throw an
`illegal_argument_exception` (HTTP 4xx).
This commit is contained in:
Adrien Grand 2017-11-21 15:31:18 +01:00 committed by GitHub
parent 5a0b6d1977
commit 6ac799074e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 1 deletions

View File

@ -473,8 +473,8 @@ public class DateFieldMapper extends FieldMapper {
@Override
protected void doMerge(Mapper mergeWith, boolean updateAllTypes) {
final DateFieldMapper other = (DateFieldMapper) mergeWith;
super.doMerge(mergeWith, updateAllTypes);
final DateFieldMapper other = (DateFieldMapper) mergeWith;
if (other.ignoreMalformed.explicit()) {
this.ignoreMalformed = other.ignoreMalformed;
}

View File

@ -395,4 +395,20 @@ public class DateFieldMapperTests extends ESSingleNodeTestCase {
MapperService.MergeReason.MAPPING_UPDATE, randomBoolean()));
assertThat(e.getMessage(), containsString("[mapper [release_date] has different [format] values]"));
}
public void testMergeText() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("doc")
.startObject("properties").startObject("date").field("type", "date").endObject()
.endObject().endObject().endObject().string();
DocumentMapper mapper = indexService.mapperService().parse("doc", new CompressedXContent(mapping), false);
String mappingUpdate = XContentFactory.jsonBuilder().startObject().startObject("doc")
.startObject("properties").startObject("date").field("type", "text").endObject()
.endObject().endObject().endObject().string();
DocumentMapper update = indexService.mapperService().parse("doc", new CompressedXContent(mappingUpdate), false);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> mapper.merge(update.mapping(), randomBoolean()));
assertEquals("mapper [date] of different type, current_type [date], merged_type [text]", e.getMessage());
}
}