Browse Source

Add a new values source type returned by metric counters (#90680)

This commit adds a new values source type to identify counter fields in
TSDB indices. Because aggregate values over this field only make sense
in specific time series contexts, this should prevent users trying to issue
nonsensical aggregations (eg, sum or avg) over counters.
Alan Woodward 2 years ago
parent
commit
34a0093928

+ 6 - 2
modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/extras/ScaledFloatFieldMapper.java

@@ -45,7 +45,7 @@ import org.elasticsearch.script.field.DocValuesScriptFieldFactory;
 import org.elasticsearch.script.field.ScaledFloatDocValuesField;
 import org.elasticsearch.script.field.ToScriptFieldFactory;
 import org.elasticsearch.search.DocValueFormat;
-import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSourceType;
 import org.elasticsearch.search.lookup.SearchLookup;
 import org.elasticsearch.xcontent.XContentBuilder;
@@ -287,11 +287,15 @@ public class ScaledFloatFieldMapper extends FieldMapper {
                 failIfNoDocValues();
             }
 
+            ValuesSourceType valuesSourceType = metricType == TimeSeriesParams.MetricType.counter
+                ? TimeSeriesValuesSourceType.COUNTER
+                : IndexNumericFieldData.NumericType.LONG.getValuesSourceType();
             if ((operation == FielddataOperation.SEARCH || operation == FielddataOperation.SCRIPT) && hasDocValues()) {
                 return (cache, breakerService) -> {
                     final IndexNumericFieldData scaledValues = new SortedNumericIndexFieldData.Builder(
                         name(),
                         IndexNumericFieldData.NumericType.LONG,
+                        valuesSourceType,
                         (dv, n) -> { throw new UnsupportedOperationException(); }
                     ).build(cache, breakerService);
                     return new ScaledFloatIndexFieldData(scaledValues, scalingFactor, ScaledFloatDocValuesField::new);
@@ -304,7 +308,7 @@ public class ScaledFloatFieldMapper extends FieldMapper {
 
                 return new SourceValueFetcherSortedDoubleIndexFieldData.Builder(
                     name(),
-                    CoreValuesSourceType.NUMERIC,
+                    valuesSourceType,
                     sourceValueFetcher(sourcePaths),
                     searchLookup.source(),
                     ScaledFloatDocValuesField::new

+ 11 - 3
server/src/main/java/org/elasticsearch/index/fielddata/plain/SortedDoublesIndexFieldData.java

@@ -40,17 +40,24 @@ public class SortedDoublesIndexFieldData extends IndexNumericFieldData {
     public static class Builder implements IndexFieldData.Builder {
         private final String name;
         private final NumericType numericType;
+        private final ValuesSourceType valuesSourceType;
         protected final ToScriptFieldFactory<SortedNumericDoubleValues> toScriptFieldFactory;
 
-        public Builder(String name, NumericType numericType, ToScriptFieldFactory<SortedNumericDoubleValues> toScriptFieldFactory) {
+        public Builder(
+            String name,
+            NumericType numericType,
+            ValuesSourceType valuesSourceType,
+            ToScriptFieldFactory<SortedNumericDoubleValues> toScriptFieldFactory
+        ) {
             this.name = name;
             this.numericType = numericType;
+            this.valuesSourceType = valuesSourceType;
             this.toScriptFieldFactory = toScriptFieldFactory;
         }
 
         @Override
         public SortedDoublesIndexFieldData build(IndexFieldDataCache cache, CircuitBreakerService breakerService) {
-            return new SortedDoublesIndexFieldData(name, numericType, toScriptFieldFactory);
+            return new SortedDoublesIndexFieldData(name, numericType, valuesSourceType, toScriptFieldFactory);
         }
     }
 
@@ -62,12 +69,13 @@ public class SortedDoublesIndexFieldData extends IndexNumericFieldData {
     public SortedDoublesIndexFieldData(
         String fieldName,
         NumericType numericType,
+        ValuesSourceType valuesSourceType,
         ToScriptFieldFactory<SortedNumericDoubleValues> toScriptFieldFactory
     ) {
         this.fieldName = fieldName;
         this.numericType = Objects.requireNonNull(numericType);
         assert this.numericType.isFloatingPoint();
-        this.valuesSourceType = numericType.getValuesSourceType();
+        this.valuesSourceType = valuesSourceType;
         this.toScriptFieldFactory = toScriptFieldFactory;
     }
 

+ 14 - 2
server/src/main/java/org/elasticsearch/index/fielddata/plain/SortedNumericIndexFieldData.java

@@ -40,17 +40,28 @@ public class SortedNumericIndexFieldData extends IndexNumericFieldData {
     public static class Builder implements IndexFieldData.Builder {
         private final String name;
         private final NumericType numericType;
+        private final ValuesSourceType valuesSourceType;
         protected final ToScriptFieldFactory<SortedNumericDocValues> toScriptFieldFactory;
 
         public Builder(String name, NumericType numericType, ToScriptFieldFactory<SortedNumericDocValues> toScriptFieldFactory) {
+            this(name, numericType, numericType.getValuesSourceType(), toScriptFieldFactory);
+        }
+
+        public Builder(
+            String name,
+            NumericType numericType,
+            ValuesSourceType valuesSourceType,
+            ToScriptFieldFactory<SortedNumericDocValues> toScriptFieldFactory
+        ) {
             this.name = name;
             this.numericType = numericType;
+            this.valuesSourceType = valuesSourceType;
             this.toScriptFieldFactory = toScriptFieldFactory;
         }
 
         @Override
         public SortedNumericIndexFieldData build(IndexFieldDataCache cache, CircuitBreakerService breakerService) {
-            return new SortedNumericIndexFieldData(name, numericType, toScriptFieldFactory);
+            return new SortedNumericIndexFieldData(name, numericType, valuesSourceType, toScriptFieldFactory);
         }
     }
 
@@ -62,12 +73,13 @@ public class SortedNumericIndexFieldData extends IndexNumericFieldData {
     public SortedNumericIndexFieldData(
         String fieldName,
         NumericType numericType,
+        ValuesSourceType valuesSourceType,
         ToScriptFieldFactory<SortedNumericDocValues> toScriptFieldFactory
     ) {
         this.fieldName = fieldName;
         this.numericType = Objects.requireNonNull(numericType);
         assert this.numericType.isFloatingPoint() == false;
-        this.valuesSourceType = numericType.getValuesSourceType();
+        this.valuesSourceType = valuesSourceType;
         this.toScriptFieldFactory = toScriptFieldFactory;
     }
 

+ 48 - 26
server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java

@@ -51,6 +51,8 @@ import org.elasticsearch.script.field.IntegerDocValuesField;
 import org.elasticsearch.script.field.LongDocValuesField;
 import org.elasticsearch.script.field.ShortDocValuesField;
 import org.elasticsearch.search.DocValueFormat;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
+import org.elasticsearch.search.aggregations.support.ValuesSourceType;
 import org.elasticsearch.search.lookup.FieldValues;
 import org.elasticsearch.search.lookup.SearchLookup;
 import org.elasticsearch.search.lookup.SourceLookup;
@@ -373,19 +375,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedDoublesIndexFieldData.Builder(name, numericType(), HalfFloatDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedDoublesIndexFieldData.Builder(name, numericType(), valuesSourceType, HalfFloatDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedDoubleIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     HalfFloatDocValuesField::new
@@ -523,19 +526,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedDoublesIndexFieldData.Builder(name, numericType(), FloatDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedDoublesIndexFieldData.Builder(name, numericType(), valuesSourceType, FloatDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedDoubleIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     FloatDocValuesField::new
@@ -651,19 +655,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedDoublesIndexFieldData.Builder(name, numericType(), DoubleDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedDoublesIndexFieldData.Builder(name, numericType(), valuesSourceType, DoubleDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedDoubleIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     DoubleDocValuesField::new
@@ -754,19 +759,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedNumericIndexFieldData.Builder(name, numericType(), ByteDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedNumericIndexFieldData.Builder(name, numericType(), valuesSourceType, ByteDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedNumericIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     ByteDocValuesField::new
@@ -842,19 +848,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedNumericIndexFieldData.Builder(name, numericType(), ShortDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedNumericIndexFieldData.Builder(name, numericType(), valuesSourceType, ShortDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedNumericIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     ShortDocValuesField::new
@@ -997,19 +1004,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedNumericIndexFieldData.Builder(name, numericType(), IntegerDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedNumericIndexFieldData.Builder(name, numericType(), valuesSourceType, IntegerDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedNumericIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     IntegerDocValuesField::new
@@ -1122,19 +1130,20 @@ public class NumberFieldMapper extends FieldMapper {
             }
 
             @Override
-            public IndexFieldData.Builder getFieldDataBuilder(String name) {
-                return new SortedNumericIndexFieldData.Builder(name, numericType(), LongDocValuesField::new);
+            public IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType) {
+                return new SortedNumericIndexFieldData.Builder(name, numericType(), valuesSourceType, LongDocValuesField::new);
             }
 
             @Override
             public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
                 String name,
+                ValuesSourceType valuesSourceType,
                 SourceLookup sourceLookup,
                 ValueFetcher valueFetcher
             ) {
                 return new SourceValueFetcherSortedNumericIndexFieldData.Builder(
                     name,
-                    numericType().getValuesSourceType(),
+                    valuesSourceType,
                     valueFetcher,
                     sourceLookup,
                     LongDocValuesField::new
@@ -1364,9 +1373,14 @@ public class NumberFieldMapper extends FieldMapper {
             return builder.apply(l, u);
         }
 
-        public abstract IndexFieldData.Builder getFieldDataBuilder(String name);
+        public abstract IndexFieldData.Builder getFieldDataBuilder(String name, ValuesSourceType valuesSourceType);
 
-        public IndexFieldData.Builder getValueFetcherFieldDataBuilder(String name, SourceLookup sourceLookup, ValueFetcher valueFetcher) {
+        public IndexFieldData.Builder getValueFetcherFieldDataBuilder(
+            String name,
+            ValuesSourceType valuesSourceType,
+            SourceLookup sourceLookup,
+            ValueFetcher valueFetcher
+        ) {
             throw new UnsupportedOperationException("not supported for source fallback");
         }
 
@@ -1530,15 +1544,23 @@ public class NumberFieldMapper extends FieldMapper {
                 failIfNoDocValues();
             }
 
+            ValuesSourceType valuesSourceType = metricType == TimeSeriesParams.MetricType.counter
+                ? TimeSeriesValuesSourceType.COUNTER
+                : type.numericType.getValuesSourceType();
+
             if ((operation == FielddataOperation.SEARCH || operation == FielddataOperation.SCRIPT) && hasDocValues()) {
-                return type.getFieldDataBuilder(name());
+                return type.getFieldDataBuilder(name(), valuesSourceType);
             }
 
             if (operation == FielddataOperation.SCRIPT) {
                 SearchLookup searchLookup = fieldDataContext.lookupSupplier().get();
                 Set<String> sourcePaths = fieldDataContext.sourcePathsLookup().apply(name());
-
-                return type.getValueFetcherFieldDataBuilder(name(), searchLookup.source(), sourceValueFetcher(sourcePaths));
+                return type.getValueFetcherFieldDataBuilder(
+                    name(),
+                    valuesSourceType,
+                    searchLookup.source(),
+                    sourceValueFetcher(sourcePaths)
+                );
             }
 
             throw new IllegalStateException("unknown field data type [" + operation.name() + "]");

+ 2 - 1
server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/HistogramValuesSourceBuilder.java

@@ -15,6 +15,7 @@ import org.elasticsearch.common.util.BigArrays;
 import org.elasticsearch.index.mapper.MappedFieldType;
 import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
 import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSource;
 import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
 import org.elasticsearch.search.aggregations.support.ValuesSourceRegistry;
@@ -68,7 +69,7 @@ public class HistogramValuesSourceBuilder extends CompositeValuesSourceBuilder<H
     public static void register(ValuesSourceRegistry.Builder builder) {
         builder.register(
             REGISTRY_KEY,
-            List.of(CoreValuesSourceType.DATE, CoreValuesSourceType.NUMERIC),
+            List.of(CoreValuesSourceType.DATE, CoreValuesSourceType.NUMERIC, TimeSeriesValuesSourceType.COUNTER),
             (valuesSourceConfig, interval, name, hasScript, format, missingBucket, missingOrder, order) -> {
                 ValuesSource.Numeric numeric = (ValuesSource.Numeric) valuesSourceConfig.getValuesSource();
                 final HistogramValuesSource vs = new HistogramValuesSource(numeric, interval);

+ 7 - 1
server/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramAggregatorFactory.java

@@ -18,6 +18,7 @@ import org.elasticsearch.search.aggregations.CardinalityUpperBound;
 import org.elasticsearch.search.aggregations.support.AggregationContext;
 import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
 import org.elasticsearch.search.aggregations.support.SamplingContext;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory;
 import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
 import org.elasticsearch.search.aggregations.support.ValuesSourceRegistry;
@@ -45,7 +46,12 @@ public final class HistogramAggregatorFactory extends ValuesSourceAggregatorFact
 
         builder.register(
             HistogramAggregationBuilder.REGISTRY_KEY,
-            List.of(CoreValuesSourceType.NUMERIC, CoreValuesSourceType.DATE, CoreValuesSourceType.BOOLEAN),
+            List.of(
+                CoreValuesSourceType.NUMERIC,
+                CoreValuesSourceType.DATE,
+                CoreValuesSourceType.BOOLEAN,
+                TimeSeriesValuesSourceType.COUNTER
+            ),
             NumericHistogramAggregator::new,
             true
         );

+ 3 - 1
server/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/VariableWidthHistogramAggregatorFactory.java

@@ -14,11 +14,13 @@ import org.elasticsearch.search.aggregations.AggregatorFactory;
 import org.elasticsearch.search.aggregations.CardinalityUpperBound;
 import org.elasticsearch.search.aggregations.support.AggregationContext;
 import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory;
 import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
 import org.elasticsearch.search.aggregations.support.ValuesSourceRegistry;
 
 import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 
 public class VariableWidthHistogramAggregatorFactory extends ValuesSourceAggregatorFactory {
@@ -26,7 +28,7 @@ public class VariableWidthHistogramAggregatorFactory extends ValuesSourceAggrega
     public static void registerAggregators(ValuesSourceRegistry.Builder builder) {
         builder.register(
             VariableWidthHistogramAggregationBuilder.REGISTRY_KEY,
-            CoreValuesSourceType.NUMERIC,
+            List.of(CoreValuesSourceType.NUMERIC, TimeSeriesValuesSourceType.COUNTER),
             VariableWidthHistogramAggregator::new,
             true
         );

+ 7 - 1
server/src/main/java/org/elasticsearch/search/aggregations/bucket/range/RangeAggregationBuilder.java

@@ -17,6 +17,7 @@ import org.elasticsearch.search.aggregations.AggregatorFactory;
 import org.elasticsearch.search.aggregations.bucket.range.RangeAggregator.Range;
 import org.elasticsearch.search.aggregations.support.AggregationContext;
 import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
 import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
 import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
 import org.elasticsearch.search.aggregations.support.ValuesSourceRegistry;
@@ -49,7 +50,12 @@ public class RangeAggregationBuilder extends AbstractRangeBuilder<RangeAggregati
     public static void registerAggregators(ValuesSourceRegistry.Builder builder) {
         builder.register(
             REGISTRY_KEY,
-            List.of(CoreValuesSourceType.NUMERIC, CoreValuesSourceType.DATE, CoreValuesSourceType.BOOLEAN),
+            List.of(
+                CoreValuesSourceType.NUMERIC,
+                CoreValuesSourceType.DATE,
+                CoreValuesSourceType.BOOLEAN,
+                TimeSeriesValuesSourceType.COUNTER
+            ),
             RangeAggregator::build,
             true
         );

+ 69 - 0
server/src/main/java/org/elasticsearch/search/aggregations/support/TimeSeriesValuesSourceType.java

@@ -0,0 +1,69 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.search.aggregations.support;
+
+import org.elasticsearch.index.fielddata.IndexNumericFieldData;
+import org.elasticsearch.script.AggregationScript;
+import org.elasticsearch.search.DocValueFormat;
+
+import java.util.Locale;
+
+/**
+ * Holds {@link ValuesSourceType} implementations for time series fields
+ */
+public enum TimeSeriesValuesSourceType implements ValuesSourceType {
+
+    COUNTER {
+        @Override
+        public ValuesSource getEmpty() {
+            throw new IllegalArgumentException("Cannot use unmapped counter field");
+        }
+
+        @Override
+        public ValuesSource getScript(AggregationScript.LeafFactory script, ValueType scriptValueType) {
+            throw new IllegalArgumentException("Cannot use scripts for time-series counters");
+        }
+
+        @Override
+        public ValuesSource getField(FieldContext fieldContext, AggregationScript.LeafFactory script, AggregationContext context) {
+            if (script != null) {
+                throw new IllegalArgumentException("Cannot use scripts for time-series counters");
+            }
+            if (fieldContext.indexFieldData()instanceof IndexNumericFieldData fieldData) {
+                return new ValuesSource.Numeric.FieldData(fieldData);
+            }
+            throw new IllegalArgumentException(
+                "Expected numeric type on field [" + fieldContext.field() + "], but got [" + fieldContext.fieldType().typeName() + "]"
+            );
+        }
+
+        @Override
+        public ValuesSource replaceMissing(
+            ValuesSource valuesSource,
+            Object rawMissing,
+            DocValueFormat docValueFormat,
+            AggregationContext context
+        ) {
+            throw new IllegalArgumentException("Cannot replace missing values for time-series counters");
+        }
+    };
+
+    public static ValuesSourceType fromString(String name) {
+        return valueOf(name.trim().toUpperCase(Locale.ROOT));
+    }
+
+    public String value() {
+        return name().toLowerCase(Locale.ROOT);
+    }
+
+    @Override
+    public String typeName() {
+        return value();
+    }
+}

+ 2 - 0
server/src/test/java/org/elasticsearch/index/mapper/DateFieldTypeTests.java

@@ -39,6 +39,7 @@ import org.elasticsearch.index.query.DateRangeIncludingNowQuery;
 import org.elasticsearch.index.query.QueryRewriteContext;
 import org.elasticsearch.index.query.SearchExecutionContext;
 import org.elasticsearch.script.field.DateNanosDocValuesField;
+import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
 
 import java.io.IOException;
 import java.time.Instant;
@@ -363,6 +364,7 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
         SortedNumericIndexFieldData fieldData = new SortedNumericIndexFieldData(
             "my_date",
             IndexNumericFieldData.NumericType.DATE_NANOSECONDS,
+            CoreValuesSourceType.DATE,
             DateNanosDocValuesField::new
         );
         // Read index and check the doc values

+ 2 - 0
server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/DiversifiedSamplerTests.java

@@ -34,6 +34,7 @@ import org.elasticsearch.script.field.DelegateDocValuesField;
 import org.elasticsearch.search.aggregations.AggregatorTestCase;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
+import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -168,6 +169,7 @@ public class DiversifiedSamplerTests extends AggregatorTestCase {
         SortedDoublesIndexFieldData fieldData = new SortedDoublesIndexFieldData(
             "price",
             IndexNumericFieldData.NumericType.DOUBLE,
+            CoreValuesSourceType.NUMERIC,
             (dv, n) -> new DelegateDocValuesField(new Doubles(new DoublesSupplier(dv)), n)
         );
         FunctionScoreQuery query = new FunctionScoreQuery(

+ 5 - 1
server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchFieldsPhaseTests.java

@@ -22,6 +22,7 @@ import org.elasticsearch.index.mapper.NestedLookup;
 import org.elasticsearch.index.query.SearchExecutionContext;
 import org.elasticsearch.search.DocValueFormat;
 import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
 import org.elasticsearch.search.fetch.FetchContext;
 import org.elasticsearch.search.fetch.FetchSubPhase;
 import org.elasticsearch.search.fetch.FetchSubPhaseProcessor;
@@ -61,7 +62,10 @@ public class FetchFieldsPhaseTests extends ESTestCase {
         SearchExecutionContext sec = mock(SearchExecutionContext.class);
         MappedFieldType fieldType = mock(MappedFieldType.class);
         when(fieldType.valueFetcher(any(), any())).thenReturn(
-            new DocValueFetcher(DocValueFormat.RAW, new SortedNumericIndexFieldData("field", IndexNumericFieldData.NumericType.LONG, null))
+            new DocValueFetcher(
+                DocValueFormat.RAW,
+                new SortedNumericIndexFieldData("field", IndexNumericFieldData.NumericType.LONG, CoreValuesSourceType.NUMERIC, null)
+            )
         );
         when(sec.getFieldType(any())).thenReturn(fieldType);
         when(sec.getMatchingFieldNames(any())).thenReturn(Set.of("field"));

+ 8 - 2
x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongFieldMapper.java

@@ -36,7 +36,8 @@ import org.elasticsearch.index.mapper.TimeSeriesParams.MetricType;
 import org.elasticsearch.index.mapper.ValueFetcher;
 import org.elasticsearch.index.query.SearchExecutionContext;
 import org.elasticsearch.search.DocValueFormat;
-import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
+import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
+import org.elasticsearch.search.aggregations.support.ValuesSourceType;
 import org.elasticsearch.search.lookup.SearchLookup;
 import org.elasticsearch.xcontent.XContentBuilder;
 import org.elasticsearch.xcontent.XContentParser;
@@ -297,11 +298,16 @@ public class UnsignedLongFieldMapper extends FieldMapper {
                 failIfNoDocValues();
             }
 
+            ValuesSourceType valuesSourceType = metricType == TimeSeriesParams.MetricType.counter
+                ? TimeSeriesValuesSourceType.COUNTER
+                : IndexNumericFieldData.NumericType.LONG.getValuesSourceType();
+
             if ((operation == FielddataOperation.SEARCH || operation == FielddataOperation.SCRIPT) && hasDocValues()) {
                 return (cache, breakerService) -> {
                     final IndexNumericFieldData signedLongValues = new SortedNumericIndexFieldData.Builder(
                         name(),
                         IndexNumericFieldData.NumericType.LONG,
+                        valuesSourceType,
                         (dv, n) -> { throw new UnsupportedOperationException(); }
                     ).build(cache, breakerService);
                     return new UnsignedLongIndexFieldData(signedLongValues, UnsignedLongDocValuesField::new);
@@ -314,7 +320,7 @@ public class UnsignedLongFieldMapper extends FieldMapper {
 
                 return new SourceValueFetcherSortedUnsignedLongIndexFieldData.Builder(
                     name(),
-                    CoreValuesSourceType.NUMERIC,
+                    valuesSourceType,
                     sourceValueFetcher(sourcePaths),
                     searchLookup.source(),
                     UnsignedLongDocValuesField::new