diff --git a/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/ValuesSourceReaderBenchmark.java b/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/ValuesSourceReaderBenchmark.java index afe8377d3e58c..11d6d6dc2e64f 100644 --- a/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/ValuesSourceReaderBenchmark.java +++ b/benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/ValuesSourceReaderBenchmark.java @@ -167,6 +167,11 @@ public String indexName() { return "benchmark"; } + @Override + public boolean forStats() { + return false; + } + @Override public SearchLookup lookup() { throw new UnsupportedOperationException(); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java index 9e792f3b5abed..dd79cdddc64bb 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java @@ -143,9 +143,9 @@ protected Object parseSourceValue(Object value) { @Override public BlockLoader blockLoader(BlockLoaderContext blContext) { // TODO: If we have doc-values we have to use them, due to BlockSourceReader.columnAtATimeReader() returning null - // if (hasDocValues()) { - // return new BlockDocValuesReader.LongsBlockLoader(name()); - // } + if (blContext.forStats() && hasDocValues()) { + return new BlockDocValuesReader.LongsBlockLoader(name()); + } // TODO: Enhance BlockLoaderContext with knowledge about preferring to load from source (see EsPhysicalOperationProviders) return new BlockSourceReader.PointsBlockLoader( valueFetcher(blContext.sourcePaths(name()), nullValue, GeometryFormatterFactory.WKT) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index 376cb1a10e2e6..61049d8ec96c8 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -649,6 +649,14 @@ public interface BlockLoaderContext { */ String indexName(); + /** + * Whether the data will be used in stats. + * This is relevant to some types, where the choice between doc-values or reading from source is dependent on the usage. + * For example, spatial types use doc-values for stats, but read from source for search because doc-values are modified + * from the original. + */ + boolean forStats(); + /** * {@link SearchLookup} used for building scripts. */ diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/AbstractScriptFieldTypeTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/AbstractScriptFieldTypeTestCase.java index 1e6401d79d3fc..8774637063294 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/AbstractScriptFieldTypeTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/AbstractScriptFieldTypeTestCase.java @@ -422,6 +422,11 @@ public String indexName() { throw new UnsupportedOperationException(); } + @Override + public boolean forStats() { + return false; + } + @Override public SearchLookup lookup() { return mockContext().lookup(); diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java index 8fd1885d4cc06..12f0fdf0edd54 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java @@ -1282,6 +1282,11 @@ public String indexName() { throw new UnsupportedOperationException(); } + @Override + public boolean forStats() { + return false; + } + @Override public SearchLookup lookup() { return searchLookup; diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/BlockReaderFactories.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/BlockReaderFactories.java index 967111a09f564..aa29fa50ef0b4 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/BlockReaderFactories.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/BlockReaderFactories.java @@ -32,7 +32,12 @@ private BlockReaderFactories() {} * @param asUnsupportedSource should the field be loaded as "unsupported"? * These will always have {@code null} values */ - public static List loaders(List searchContexts, String fieldName, boolean asUnsupportedSource) { + public static List loaders( + List searchContexts, + String fieldName, + boolean asUnsupportedSource, + final boolean forStats + ) { List loaders = new ArrayList<>(searchContexts.size()); for (SearchContext searchContext : searchContexts) { @@ -53,6 +58,11 @@ public String indexName() { return ctx.getFullyQualifiedIndex().getName(); } + @Override + public boolean forStats() { + return forStats; + } + @Override public SearchLookup lookup() { return ctx.lookup(); diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/lucene/ValuesSourceReaderOperatorTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/lucene/ValuesSourceReaderOperatorTests.java index f6310d826c989..2133395ef532b 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/lucene/ValuesSourceReaderOperatorTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/lucene/ValuesSourceReaderOperatorTests.java @@ -363,6 +363,11 @@ public String indexName() { return "test_index"; } + @Override + public boolean forStats() { + return false; + } + @Override public SearchLookup lookup() { throw new UnsupportedOperationException(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/enrich/EnrichLookupService.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/enrich/EnrichLookupService.java index 945f543329c15..298ef4737c253 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/enrich/EnrichLookupService.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/enrich/EnrichLookupService.java @@ -276,7 +276,8 @@ private void doLookup( var loaders = BlockReaderFactories.loaders( List.of(searchContext), extractField instanceof Alias a ? ((NamedExpression) a.child()).name() : extractField.name(), - EsqlDataTypes.isUnsupported(extractField.dataType()) + EsqlDataTypes.isUnsupported(extractField.dataType()), + false ); fields.add(new ValuesSourceReaderOperator.FieldInfo(extractField.name(), loaders)); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java index f691c2dcf42bb..92852b692cb9e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsPhysicalOperationProviders.java @@ -78,7 +78,12 @@ public final PhysicalOperation fieldExtractPhysicalOperation(FieldExtractExec fi layout.append(attr); DataType dataType = attr.dataType(); String fieldName = attr.name(); - List loaders = BlockReaderFactories.loaders(searchContexts, fieldName, EsqlDataTypes.isUnsupported(dataType)); + List loaders = BlockReaderFactories.loaders( + searchContexts, + fieldName, + EsqlDataTypes.isUnsupported(dataType), + false + ); fields.add(new ValuesSourceReaderOperator.FieldInfo(fieldName, loaders)); } return source.with(new ValuesSourceReaderOperator.Factory(fields, readers, docChannel), layout.build()); @@ -169,7 +174,7 @@ public final Operator.OperatorFactory ordinalGroupingOperatorFactory( // The grouping-by values are ready, let's group on them directly. // Costin: why are they ready and not already exposed in the layout? return new OrdinalsGroupingOperator.OrdinalsGroupingOperatorFactory( - BlockReaderFactories.loaders(searchContexts, attrSource.name(), EsqlDataTypes.isUnsupported(attrSource.dataType())), + BlockReaderFactories.loaders(searchContexts, attrSource.name(), EsqlDataTypes.isUnsupported(attrSource.dataType()), true), shardContexts, groupElementType, docChannel, diff --git a/x-pack/plugin/mapper-constant-keyword/src/test/java/org/elasticsearch/xpack/constantkeyword/mapper/ConstantKeywordFieldMapperTests.java b/x-pack/plugin/mapper-constant-keyword/src/test/java/org/elasticsearch/xpack/constantkeyword/mapper/ConstantKeywordFieldMapperTests.java index 1bd591a827059..3d81a2b65e8bd 100644 --- a/x-pack/plugin/mapper-constant-keyword/src/test/java/org/elasticsearch/xpack/constantkeyword/mapper/ConstantKeywordFieldMapperTests.java +++ b/x-pack/plugin/mapper-constant-keyword/src/test/java/org/elasticsearch/xpack/constantkeyword/mapper/ConstantKeywordFieldMapperTests.java @@ -239,6 +239,11 @@ public String indexName() { throw new UnsupportedOperationException(); } + @Override + public boolean forStats() { + return false; + } + @Override public SearchLookup lookup() { throw new UnsupportedOperationException();