Browse Source

Binary field enables doc values by default for index mode with synthetic source (#107739)

Binary field enables doc values by default for index mode with synthetic source
Oleksandr Kolomiiets 1 year ago
parent
commit
75b5efede4

+ 6 - 0
docs/changelog/107739.yaml

@@ -0,0 +1,6 @@
+pr: 107739
+summary: Binary field enables doc values by default for index mode with synthe…
+area: Mapping
+type: enhancement
+issues:
+ - 107554

+ 2 - 1
modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java

@@ -189,7 +189,8 @@ public class PercolatorFieldMapper extends FieldMapper {
         }
 
         static BinaryFieldMapper createQueryBuilderFieldBuilder(MapperBuilderContext context) {
-            BinaryFieldMapper.Builder builder = new BinaryFieldMapper.Builder(QUERY_BUILDER_FIELD_NAME, true);
+            BinaryFieldMapper.Builder builder = new BinaryFieldMapper.Builder(QUERY_BUILDER_FIELD_NAME, context.isSourceSynthetic())
+                .docValues(true);
             return builder.build(context);
         }
 

+ 16 - 9
server/src/main/java/org/elasticsearch/index/mapper/BinaryFieldMapper.java

@@ -46,16 +46,15 @@ public class BinaryFieldMapper extends FieldMapper {
     public static class Builder extends FieldMapper.Builder {
 
         private final Parameter<Boolean> stored = Parameter.storeParam(m -> toType(m).stored, false);
-        private final Parameter<Boolean> hasDocValues = Parameter.docValuesParam(m -> toType(m).hasDocValues, false);
         private final Parameter<Map<String, String>> meta = Parameter.metaParam();
 
-        public Builder(String name) {
-            this(name, false);
-        }
+        private final boolean isSyntheticSourceEnabledViaIndexMode;
+        private final Parameter<Boolean> hasDocValues;
 
-        public Builder(String name, boolean hasDocValues) {
+        public Builder(String name, boolean isSyntheticSourceEnabledViaIndexMode) {
             super(name);
-            this.hasDocValues.setValue(hasDocValues);
+            this.isSyntheticSourceEnabledViaIndexMode = isSyntheticSourceEnabledViaIndexMode;
+            this.hasDocValues = Parameter.docValuesParam(m -> toType(m).hasDocValues, isSyntheticSourceEnabledViaIndexMode);
         }
 
         @Override
@@ -63,6 +62,11 @@ public class BinaryFieldMapper extends FieldMapper {
             return new Parameter<?>[] { meta, stored, hasDocValues };
         }
 
+        public BinaryFieldMapper.Builder docValues(boolean hasDocValues) {
+            this.hasDocValues.setValue(hasDocValues);
+            return this;
+        }
+
         @Override
         public BinaryFieldMapper build(MapperBuilderContext context) {
             return new BinaryFieldMapper(
@@ -75,10 +79,11 @@ public class BinaryFieldMapper extends FieldMapper {
         }
     }
 
-    public static final TypeParser PARSER = new TypeParser((n, c) -> new Builder(n));
+    public static final TypeParser PARSER = new TypeParser(
+        (n, c) -> new Builder(n, c.getIndexSettings().getMode().isSyntheticSourceEnabled())
+    );
 
     public static final class BinaryFieldType extends MappedFieldType {
-
         private BinaryFieldType(String name, boolean isStored, boolean hasDocValues, Map<String, String> meta) {
             super(name, false, isStored, hasDocValues, TextSearchInfo.NONE, meta);
         }
@@ -135,6 +140,7 @@ public class BinaryFieldMapper extends FieldMapper {
 
     private final boolean stored;
     private final boolean hasDocValues;
+    private final boolean isSyntheticSourceEnabledViaIndexMode;
 
     protected BinaryFieldMapper(
         String simpleName,
@@ -146,6 +152,7 @@ public class BinaryFieldMapper extends FieldMapper {
         super(simpleName, mappedFieldType, multiFields, copyTo);
         this.stored = builder.stored.getValue();
         this.hasDocValues = builder.hasDocValues.getValue();
+        this.isSyntheticSourceEnabledViaIndexMode = builder.isSyntheticSourceEnabledViaIndexMode;
     }
 
     @Override
@@ -185,7 +192,7 @@ public class BinaryFieldMapper extends FieldMapper {
 
     @Override
     public FieldMapper.Builder getMergeBuilder() {
-        return new BinaryFieldMapper.Builder(simpleName()).init(this);
+        return new BinaryFieldMapper.Builder(simpleName(), isSyntheticSourceEnabledViaIndexMode).init(this);
     }
 
     @Override

+ 4 - 1
server/src/main/java/org/elasticsearch/index/mapper/DynamicFieldsBuilder.java

@@ -411,7 +411,10 @@ final class DynamicFieldsBuilder {
         }
 
         boolean newDynamicBinaryField(DocumentParserContext context, String name) throws IOException {
-            return createDynamicField(new BinaryFieldMapper.Builder(name), context);
+            return createDynamicField(
+                new BinaryFieldMapper.Builder(name, context.indexSettings().getMode().isSyntheticSourceEnabled()),
+                context
+            );
         }
     }
 

+ 4 - 1
server/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTestCase.java

@@ -161,7 +161,10 @@ public abstract class AbstractFieldDataTestCase extends ESSingleNodeTestCase {
                 docValues
             ).build(context).fieldType();
         } else if (type.equals("binary")) {
-            fieldType = new BinaryFieldMapper.Builder(fieldName, docValues).build(context).fieldType();
+            fieldType = new BinaryFieldMapper.Builder(fieldName, indexService.getIndexSettings().getMode().isSyntheticSourceEnabled())
+                .docValues(docValues)
+                .build(context)
+                .fieldType();
         } else {
             throw new UnsupportedOperationException(type);
         }

+ 43 - 0
server/src/test/java/org/elasticsearch/index/mapper/BinaryFieldMapperTests.java

@@ -8,14 +8,18 @@
 
 package org.elasticsearch.index.mapper;
 
+import org.apache.lucene.index.DocValuesType;
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.cluster.metadata.IndexMetadata;
 import org.elasticsearch.common.bytes.BytesArray;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.compress.CompressorFactory;
 import org.elasticsearch.common.io.stream.BytesStreamOutput;
 import org.elasticsearch.core.Tuple;
+import org.elasticsearch.index.IndexMode;
+import org.elasticsearch.index.IndexSettings;
 import org.elasticsearch.xcontent.XContentBuilder;
 import org.junit.AssumptionViolatedException;
 
@@ -134,6 +138,45 @@ public class BinaryFieldMapperTests extends MapperTestCase {
         }
     }
 
+    public void testDefaultsForTimeSeriesIndex() throws IOException {
+        var isStored = randomBoolean();
+
+        var indexSettings = getIndexSettingsBuilder().put(IndexSettings.MODE.getKey(), IndexMode.TIME_SERIES)
+            .putList(IndexMetadata.INDEX_ROUTING_PATH.getKey(), "dimension")
+            .put(IndexSettings.TIME_SERIES_START_TIME.getKey(), "2000-01-08T23:40:53.384Z")
+            .put(IndexSettings.TIME_SERIES_END_TIME.getKey(), "2106-01-08T23:40:53.384Z")
+            .build();
+
+        var mapping = mapping(b -> {
+            b.startObject("field");
+            b.field("type", "binary");
+            if (isStored) {
+                b.field("store", "true");
+            }
+            b.endObject();
+
+            b.startObject("@timestamp");
+            b.field("type", "date");
+            b.endObject();
+            b.startObject("dimension");
+            b.field("type", "keyword");
+            b.field("time_series_dimension", "true");
+            b.endObject();
+        });
+        DocumentMapper mapper = createMapperService(getVersion(), indexSettings, () -> true, mapping).documentMapper();
+
+        var source = source(TimeSeriesRoutingHashFieldMapper.DUMMY_ENCODED_VALUE, b -> {
+            b.field("field", Base64.getEncoder().encodeToString(randomByteArrayOfLength(10)));
+            b.field("@timestamp", randomMillisUpToYear9999());
+            b.field("dimension", "dimension1");
+        }, null);
+        ParsedDocument doc = mapper.parse(source);
+
+        List<IndexableField> fields = doc.rootDoc().getFields("field");
+        var docValuesField = fields.stream().filter(f -> f.fieldType().docValuesType() == DocValuesType.BINARY).findFirst();
+        assertTrue("Doc values are not present", docValuesField.isPresent());
+    }
+
     @Override
     protected Object generateRandomInputValue(MappedFieldType ft) {
         if (rarely()) return null;

+ 4 - 1
x-pack/plugin/mapper-counted-keyword/src/main/java/org/elasticsearch/xpack/countedkeyword/CountedKeywordFieldMapper.java

@@ -289,7 +289,10 @@ public class CountedKeywordFieldMapper extends FieldMapper {
         @Override
         public FieldMapper build(MapperBuilderContext context) {
 
-            BinaryFieldMapper countFieldMapper = new BinaryFieldMapper.Builder(name() + COUNT_FIELD_NAME_SUFFIX, true).build(context);
+            BinaryFieldMapper countFieldMapper = new BinaryFieldMapper.Builder(
+                name() + COUNT_FIELD_NAME_SUFFIX,
+                context.isSourceSynthetic()
+            ).docValues(true).build(context);
             boolean isIndexed = indexed.getValue();
             FieldType ft = isIndexed ? FIELD_TYPE_INDEXED : FIELD_TYPE_NOT_INDEXED;
             return new CountedKeywordFieldMapper(