Fix merging of text field mapper (#40627)

On mapping updates the `text` field mapper does not update
the field types for the underlying prefix and phrase fields.
In practice this shouldn't be considered as a bug but we have
an assert in the code that check that field types in the mapper service
are identical to the ones present in field mappers.
This commit is contained in:
Jim Ferenczi 2019-04-01 08:41:08 +02:00 committed by jimczi
parent 74bf4b8292
commit 7cc79123df
2 changed files with 110 additions and 3 deletions

View File

@ -813,18 +813,33 @@ public class TextFieldMapper extends FieldMapper {
return CONTENT_TYPE;
}
@Override
public FieldMapper updateFieldType(Map<String, MappedFieldType> fullNameToFieldType) {
TextFieldMapper mapper = (TextFieldMapper) super.updateFieldType(fullNameToFieldType);
if (mapper.prefixFieldMapper != null) {
mapper.prefixFieldMapper = (PrefixFieldMapper) mapper.prefixFieldMapper.updateFieldType(fullNameToFieldType);
}
if (mapper.phraseFieldMapper != null) {
mapper.phraseFieldMapper = (PhraseFieldMapper) mapper.phraseFieldMapper.updateFieldType(fullNameToFieldType);
}
return mapper;
}
@Override
protected void doMerge(Mapper mergeWith) {
super.doMerge(mergeWith);
TextFieldMapper mw = (TextFieldMapper) mergeWith;
if (this.prefixFieldMapper != null && mw.prefixFieldMapper != null) {
this.prefixFieldMapper = (PrefixFieldMapper) this.prefixFieldMapper.merge(mw.prefixFieldMapper);
}
else if (this.prefixFieldMapper != null || mw.prefixFieldMapper != null) {
} else if (this.prefixFieldMapper != null || mw.prefixFieldMapper != null) {
throw new IllegalArgumentException("mapper [" + name() + "] has different index_prefix settings, current ["
+ this.prefixFieldMapper + "], merged [" + mw.prefixFieldMapper + "]");
}
else if (this.fieldType().indexPhrases != mw.fieldType().indexPhrases) {
if (this.phraseFieldMapper != null && mw.phraseFieldMapper != null) {
this.phraseFieldMapper = (PhraseFieldMapper) this.phraseFieldMapper.merge(mw.phraseFieldMapper);
} else if (this.fieldType().indexPhrases != mw.fieldType().indexPhrases) {
throw new IllegalArgumentException("mapper [" + name() + "] has different index_phrases settings, current ["
+ this.fieldType().indexPhrases + "], merged [" + mw.fieldType().indexPhrases + "]");
}

View File

@ -78,6 +78,7 @@ import java.util.Map;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.core.Is.is;
public class TextFieldMapperTests extends ESSingleNodeTestCase {
@ -1084,4 +1085,95 @@ public class TextFieldMapperTests extends ESSingleNodeTestCase {
assertThat(q, equalTo(mpq));
}
}
public void testSimpleMerge() throws IOException {
MapperService mapperService = createIndex("test_mapping_merge").mapperService();
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "text")
.startObject("index_prefixes").endObject()
.field("index_phrases", true)
.endObject()
.endObject()
.endObject().endObject());
DocumentMapper mapper = mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertThat(mapper.mappers().getMapper("a_field"), instanceOf(TextFieldMapper.class));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "text")
.startObject("index_prefixes").endObject()
.field("index_phrases", true)
.endObject()
.endObject()
.endObject().endObject());
DocumentMapper mapper = mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertThat(mapper.mappers().getMapper("a_field"), instanceOf(TextFieldMapper.class));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "text")
.startObject("index_prefixes")
.field("min_chars", "3")
.endObject()
.field("index_phrases", true)
.endObject()
.endObject()
.endObject().endObject());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE));
assertThat(e.getMessage(), containsString("different [index_prefixes]"));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "text")
.startObject("index_prefixes").endObject()
.field("index_phrases", false)
.endObject()
.endObject()
.endObject().endObject());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE));
assertThat(e.getMessage(), containsString("different [index_phrases]"));
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "text")
.startObject("index_prefixes").endObject()
.field("index_phrases", true)
.endObject()
.startObject("b_field")
.field("type", "keyword")
.endObject()
.endObject()
.endObject().endObject());
DocumentMapper mapper = mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertThat(mapper.mappers().getMapper("a_field"), instanceOf(TextFieldMapper.class));
assertThat(mapper.mappers().getMapper("b_field"), instanceOf(KeywordFieldMapper.class));
}
}
}