diff --git a/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java index dc74fa33a98..b68be28e2f1 100644 --- a/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java @@ -294,7 +294,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { protected final Names names; protected float boost; protected FieldType fieldType; - protected final boolean docValues; + protected final Boolean docValues; protected final NamedAnalyzer indexAnalyzer; protected NamedAnalyzer searchAnalyzer; protected final SimilarityProvider similarity; @@ -349,13 +349,9 @@ public abstract class AbstractFieldMapper implements FieldMapper { } else if (fieldDataType != null && FieldDataType.DOC_VALUES_FORMAT_VALUE.equals(fieldDataType.getFormat(indexSettings))) { // convoluted way to enable doc values, should be removed in the future this.docValues = true; - } else if (Version.indexCreated(indexSettings).onOrAfter(Version.V_2_0_0)) { - // 2.0+ index, default to true when appropriate - this.docValues = defaultDocValues(); } else { - // old default, disable - this.docValues = false; - } + this.docValues = null; // use the default + } this.multiFields = multiFields; this.copyTo = copyTo; } @@ -380,7 +376,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { @Override public final boolean hasDocValues() { - return docValues; + return docValues == null ? defaultDocValues() : docValues; } @Override @@ -723,9 +719,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { if (includeDefaults || fieldType.stored() != defaultFieldType.stored()) { builder.field("store", fieldType.stored()); } - if (includeDefaults || hasDocValues() != defaultDocValues()) { - builder.field(TypeParsers.DOC_VALUES, docValues); - } + doXContentDocValues(builder, includeDefaults); if (includeDefaults || fieldType.storeTermVectors() != defaultFieldType.storeTermVectors()) { builder.field("term_vector", termVectorOptionsToString(fieldType)); } @@ -778,6 +772,12 @@ public abstract class AbstractFieldMapper implements FieldMapper { } } } + + protected void doXContentDocValues(XContentBuilder builder, boolean includeDefaults) throws IOException { + if (includeDefaults || docValues != null) { + builder.field(TypeParsers.DOC_VALUES, hasDocValues()); + } + } protected static String indexOptionToString(IndexOptions indexOption) { switch (indexOption) { diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java index 217b10f45ef..f8fa3984ef5 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java @@ -42,7 +42,6 @@ import org.elasticsearch.index.mapper.RootMapper; import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.elasticsearch.index.mapper.core.LongFieldMapper; import org.elasticsearch.index.mapper.core.NumberFieldMapper; -import org.elasticsearch.index.mapper.core.TypeParsers; import java.io.IOException; import java.util.Iterator; @@ -328,9 +327,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap if (includeDefaults || fieldType.stored() != Defaults.FIELD_TYPE.stored()) { builder.field("store", fieldType.stored()); } - if (includeDefaults || hasDocValues() != defaultDocValues()) { - builder.field(TypeParsers.DOC_VALUES, docValues); - } + doXContentDocValues(builder, includeDefaults); if (includeDefaults || path != Defaults.PATH) { builder.field("path", path); } diff --git a/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java index 5284cc3f7b1..d81168de38b 100644 --- a/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java @@ -664,10 +664,10 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { mapping2.endObject() .endObject().endObject(); - testConflict(mapping1.string(), mapping2.string(), parser, (path1 == path2 ? null : "Cannot update path in _timestamp value")); + assertConflict(mapping1.string(), mapping2.string(), parser, (path1 == path2 ? null : "Cannot update path in _timestamp value")); } - void testConflict(String mapping1, String mapping2, DocumentMapperParser parser, String conflict) throws IOException { + void assertConflict(String mapping1, String mapping2, DocumentMapperParser parser, String conflict) throws IOException { DocumentMapper docMapper = parser.parse(mapping1); docMapper.refreshSource(); docMapper = parser.parse(docMapper.mappingSource().string()); @@ -677,4 +677,59 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { assertThat(mergeResult.conflicts()[0], containsString(conflict)); } } + + public void testDocValuesSerialization() throws Exception { + // default + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp") + .endObject().endObject().endObject().string(); + assertDocValuesSerialization(mapping); + + // just format specified + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp") + .startObject("fielddata").field("format", "doc_values").endObject() + .endObject().endObject().endObject().string(); + assertDocValuesSerialization(mapping); + + // explicitly enabled + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp") + .field("doc_values", true) + .endObject().endObject().endObject().string(); + assertDocValuesSerialization(mapping); + + // explicitly disabled + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp") + .field("doc_values", false) + .endObject().endObject().endObject().string(); + assertDocValuesSerialization(mapping); + + // explicitly enabled, with format + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp") + .field("doc_values", true) + .startObject("fielddata").field("format", "doc_values").endObject() + .endObject().endObject().endObject().string(); + assertDocValuesSerialization(mapping); + + // explicitly disabled, with format + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp") + .field("doc_values", false) + .startObject("fielddata").field("format", "doc_values").endObject() + .endObject().endObject().endObject().string(); + assertDocValuesSerialization(mapping); + } + + void assertDocValuesSerialization(String mapping) throws Exception { + DocumentMapperParser parser = createIndex("test_doc_values").mapperService().documentMapperParser(); + DocumentMapper docMapper = parser.parse(mapping); + boolean docValues= docMapper.timestampFieldMapper().hasDocValues(); + docMapper.refreshSource(); + docMapper = parser.parse(docMapper.mappingSource().string()); + assertThat(docMapper.timestampFieldMapper().hasDocValues(), equalTo(docValues)); + assertAcked(client().admin().indices().prepareDelete("test_doc_values")); + } }