From 6ac799074e5dc3fb5193895dbbe0521c8af9e995 Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Tue, 21 Nov 2017 15:31:18 +0100 Subject: [PATCH] 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). --- .../index/mapper/DateFieldMapper.java | 2 +- .../index/mapper/DateFieldMapperTests.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java index 36e7a73aa9a..3b21a3bd740 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java @@ -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; } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java index b728c44cc65..7a4749bcb3c 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java @@ -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()); + } }