Fix merging of search_as_you_type field mapper (#40593)

The merge of the `search_as_you_type` field mapper uses the wrong prefix field
and does not update the underlying field types.
This commit is contained in:
Jim Ferenczi 2019-03-29 09:01:36 +01:00 committed by jimczi
parent 8aca08bf52
commit e256eb361a
2 changed files with 68 additions and 3 deletions

View File

@ -516,7 +516,7 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
@Override @Override
protected String contentType() { protected String contentType() {
return CONTENT_TYPE; return "shingle";
} }
} }
@ -663,6 +663,16 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
this.maxShingleSize = maxShingleSize; this.maxShingleSize = maxShingleSize;
} }
@Override
public FieldMapper updateFieldType(Map<String, MappedFieldType> fullNameToFieldType) {
SearchAsYouTypeFieldMapper fieldMapper = (SearchAsYouTypeFieldMapper) super.updateFieldType(fullNameToFieldType);
fieldMapper.prefixField = (PrefixFieldMapper) fieldMapper.prefixField.updateFieldType(fullNameToFieldType);
for (int i = 0; i < fieldMapper.shingleFields.length; i++) {
fieldMapper.shingleFields[i] = (ShingleFieldMapper) fieldMapper.shingleFields[i].updateFieldType(fullNameToFieldType);
}
return fieldMapper;
}
@Override @Override
protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException { protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException {
final String value = context.externalValueSet() ? context.externalValue().toString() : context.parser().textOrNull(); final String value = context.externalValueSet() ? context.externalValue().toString() : context.parser().textOrNull();
@ -692,10 +702,10 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
super.doMerge(mergeWith); super.doMerge(mergeWith);
SearchAsYouTypeFieldMapper mw = (SearchAsYouTypeFieldMapper) mergeWith; SearchAsYouTypeFieldMapper mw = (SearchAsYouTypeFieldMapper) mergeWith;
if (mw.maxShingleSize != maxShingleSize) { if (mw.maxShingleSize != maxShingleSize) {
throw new IllegalArgumentException("mapper [" + name() + "] has different maxShingleSize setting, current [" throw new IllegalArgumentException("mapper [" + name() + "] has different [max_shingle_size] setting, current ["
+ this.maxShingleSize + "], merged [" + mw.maxShingleSize + "]"); + this.maxShingleSize + "], merged [" + mw.maxShingleSize + "]");
} }
this.prefixField = (PrefixFieldMapper) this.prefixField.merge(mw); this.prefixField = (PrefixFieldMapper) this.prefixField.merge(mw.prefixField);
ShingleFieldMapper[] shingleFieldMappers = new ShingleFieldMapper[mw.shingleFields.length]; ShingleFieldMapper[] shingleFieldMappers = new ShingleFieldMapper[mw.shingleFields.length];
for (int i = 0; i < shingleFieldMappers.length; i++) { for (int i = 0; i < shingleFieldMappers.length; i++) {

View File

@ -71,6 +71,7 @@ import java.util.stream.Stream;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasProperty; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasProperty;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
@ -180,6 +181,60 @@ public class SearchAsYouTypeFieldMapperTests extends ESSingleNodeTestCase {
getShingleFieldMapper(defaultMapper, "a_field._4gram").fieldType(), 4, analyzerName, prefixFieldMapper.fieldType()); getShingleFieldMapper(defaultMapper, "a_field._4gram").fieldType(), 4, analyzerName, prefixFieldMapper.fieldType());
} }
public void testSimpleMerge() throws IOException {
MapperService mapperService = createIndex("test").mapperService();
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "search_as_you_type")
.field("analyzer", "standard")
.endObject()
.endObject()
.endObject().endObject());
DocumentMapper mapper = mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "search_as_you_type")
.field("analyzer", "standard")
.endObject()
.startObject("b_field")
.field("type", "text")
.endObject()
.endObject()
.endObject().endObject());
DocumentMapper mapper = mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
}
{
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
.startObject("_doc")
.startObject("properties")
.startObject("a_field")
.field("type", "search_as_you_type")
.field("analyzer", "standard")
.field("max_shingle_size", "4")
.endObject()
.startObject("b_field")
.field("type", "text")
.endObject()
.endObject()
.endObject().endObject());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> mapperService.merge("_doc",
new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE));
assertThat(e.getMessage(), containsString("different [max_shingle_size]"));
}
}
public void testIndexOptions() throws IOException { public void testIndexOptions() throws IOException {
final String mapping = Strings.toString(XContentFactory.jsonBuilder() final String mapping = Strings.toString(XContentFactory.jsonBuilder()
.startObject() .startObject()