From 12477f38b4890d86cb98bea30f70c0dc17d18393 Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Wed, 27 Jan 2016 11:00:19 +0100 Subject: [PATCH] Fix serialization of `search_analyzer`. We currently have a bug that it will be omitted if the index analyzer is the default analyzer. --- .../index/mapper/FieldMapper.java | 23 ++++++++++----- .../index/mapper/core/StringFieldMapper.java | 12 ++------ .../string/SimpleStringMappingTests.java | 28 +++++++++++++++++++ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java index a9838503566..fd35398a9dc 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -421,8 +421,6 @@ public abstract class FieldMapper extends Mapper implements Cloneable { builder.field("index_options", indexOptionToString(fieldType().indexOptions())); } - doXContentAnalyzers(builder, includeDefaults); - if (fieldType().similarity() != null) { builder.field("similarity", fieldType().similarity().name()); } else if (includeDefaults) { @@ -439,15 +437,26 @@ public abstract class FieldMapper extends Mapper implements Cloneable { } } - protected void doXContentAnalyzers(XContentBuilder builder, boolean includeDefaults) throws IOException { + protected final void doXContentAnalyzers(XContentBuilder builder, boolean includeDefaults) throws IOException { + if (fieldType.tokenized() == false) { + return; + } if (fieldType().indexAnalyzer() == null) { if (includeDefaults) { builder.field("analyzer", "default"); } - } else if (includeDefaults || fieldType().indexAnalyzer().name().startsWith("_") == false && fieldType().indexAnalyzer().name().equals("default") == false) { - builder.field("analyzer", fieldType().indexAnalyzer().name()); - if (fieldType().searchAnalyzer().name().equals(fieldType().indexAnalyzer().name()) == false) { - builder.field("search_analyzer", fieldType().searchAnalyzer().name()); + } else { + boolean hasDefaultIndexAnalyzer = fieldType().indexAnalyzer().name().equals("default"); + boolean hasDifferentSearchAnalyzer = fieldType().searchAnalyzer().name().equals(fieldType().indexAnalyzer().name()) == false; + boolean hasDifferentSearchQuoteAnalyzer = fieldType().searchAnalyzer().name().equals(fieldType().searchQuoteAnalyzer().name()) == false; + if (includeDefaults || hasDefaultIndexAnalyzer == false || hasDifferentSearchAnalyzer || hasDifferentSearchQuoteAnalyzer) { + builder.field("analyzer", fieldType().indexAnalyzer().name()); + if (hasDifferentSearchAnalyzer || hasDifferentSearchQuoteAnalyzer) { + builder.field("search_analyzer", fieldType().searchAnalyzer().name()); + if (hasDifferentSearchQuoteAnalyzer) { + builder.field("search_quote_analyzer", fieldType().searchQuoteAnalyzer().name()); + } + } } } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java index 918731d0244..05ef8c88e0c 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java @@ -404,6 +404,7 @@ public class StringFieldMapper extends FieldMapper implements AllFieldMapper.Inc @Override protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException { super.doXContentBody(builder, includeDefaults, params); + doXContentAnalyzers(builder, includeDefaults); if (includeDefaults || fieldType().nullValue() != null) { builder.field("null_value", fieldType().nullValue()); @@ -417,16 +418,7 @@ public class StringFieldMapper extends FieldMapper implements AllFieldMapper.Inc if (includeDefaults || positionIncrementGap != POSITION_INCREMENT_GAP_USE_ANALYZER) { builder.field("position_increment_gap", positionIncrementGap); } - NamedAnalyzer searchQuoteAnalyzer = fieldType().searchQuoteAnalyzer(); - if (searchQuoteAnalyzer != null && !searchQuoteAnalyzer.name().equals(fieldType().searchAnalyzer().name())) { - builder.field("search_quote_analyzer", searchQuoteAnalyzer.name()); - } else if (includeDefaults) { - if (searchQuoteAnalyzer == null) { - builder.field("search_quote_analyzer", "default"); - } else { - builder.field("search_quote_analyzer", searchQuoteAnalyzer.name()); - } - } + if (includeDefaults || ignoreAbove != Defaults.IGNORE_ABOVE) { builder.field("ignore_above", ignoreAbove); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java index 6114185ccf6..f100182ebf5 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java @@ -50,6 +50,7 @@ import org.elasticsearch.test.InternalSettingsPlugin; import org.elasticsearch.test.VersionUtils; import org.junit.Before; +import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.Map; @@ -280,6 +281,33 @@ public class SimpleStringMappingTests extends ESSingleNodeTestCase { } } + public void testSearchAnalyzerSerialization() throws IOException { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties") + .startObject("field") + .field("type", "string") + .field("analyzer", "standard") + .field("search_analyzer", "keyword") + .endObject() + .endObject().endObject().endObject().string(); + + DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping)); + assertEquals(mapping, mapper.mappingSource().toString()); + + // special case: default index analyzer + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties") + .startObject("field") + .field("type", "string") + .field("analyzer", "default") + .field("search_analyzer", "keyword") + .endObject() + .endObject().endObject().endObject().string(); + + mapper = parser.parse("type", new CompressedXContent(mapping)); + assertEquals(mapping, mapper.mappingSource().toString()); + } + private Map getSerializedMap(String fieldName, DocumentMapper mapper) throws Exception { FieldMapper fieldMapper = mapper.mappers().smartNameFieldMapper(fieldName); XContentBuilder builder = JsonXContent.contentBuilder().startObject();