diff --git a/docs/changelog/122376.yaml b/docs/changelog/122376.yaml new file mode 100644 index 0000000000000..41a1730722b3a --- /dev/null +++ b/docs/changelog/122376.yaml @@ -0,0 +1,6 @@ +pr: 122376 +summary: Index-time scripted fields to be fetched from doc values +area: Search +type: bug +issues: + - 119939 diff --git a/modules/runtime-fields-common/build.gradle b/modules/runtime-fields-common/build.gradle index 0cbb6a4d43c97..77f97c8a8fc7a 100644 --- a/modules/runtime-fields-common/build.gradle +++ b/modules/runtime-fields-common/build.gradle @@ -22,3 +22,10 @@ dependencies { api project(':libs:grok') api project(':libs:dissect') } + +tasks.named("yamlRestCompatTestTransform").configure ({ task -> + task.skipTest("runtime_fields/13_keyword_calculated_at_index/fetch fields", "Script no longer executed at fetch time") + task.skipTest("runtime_fields/23_long_calculated_at_index/fetch fields", "Script no longer executed at fetch time") + task.skipTest("runtime_fields/33_double_calculated_at_index/fetch fields", "Script no longer executed at fetch time") + task.skipTest("runtime_fields/103_geo_point_calculated_at_index/fetch fields from source", "Script no longer executed at fetch time") +}) diff --git a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/103_geo_point_calculated_at_index.yml b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/103_geo_point_calculated_at_index.yml index 486eab827379c..dc3ef38592219 100644 --- a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/103_geo_point_calculated_at_index.yml +++ b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/103_geo_point_calculated_at_index.yml @@ -64,13 +64,25 @@ setup: - match: {hits.total.value: 6} - match: {hits.hits.0.fields.location.0.type: "Point" } - match: {hits.hits.0.fields.location.0.coordinates: [34.89, 13.5] } - # calculated from scripts adds annoying extra precision - - match: { hits.hits.0.fields.location_from_doc_value.0.type: "Point" } - - match: { hits.hits.0.fields.location_from_doc_value.0.coordinates: [ 34.889999935403466, 13.499999991618097 ] } - - match: { hits.hits.0.fields.location_from_source.0.type: "Point" } - - match: { hits.hits.0.fields.location_from_source.0.coordinates: [ 34.89, 13.5 ] } + - match: { hits.hits.0.fields.location_from_doc_value.0: "13.499999991618097, 34.889999935403466" } + - match: { hits.hits.0.fields.location_from_source.0: "13.499999991618097, 34.889999935403466" } --- +"docvalue_fields": + - do: + search: + index: locations + body: + sort: timestamp + docvalue_fields: + - location + - location_from_doc_value + - location_from_source + - match: {hits.total.value: 6} + - match: { hits.hits.0.fields.location.0: "13.499999991618097, 34.889999935403466" } + - match: { hits.hits.0.fields.location_from_doc_value.0: "13.499999991618097, 34.889999935403466" } + - match: { hits.hits.0.fields.location_from_source.0: "13.499999991618097, 34.889999935403466" } +--- "exists query": - do: search: diff --git a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/13_keyword_calculated_at_index.yml b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/13_keyword_calculated_at_index.yml index c27ddab72bff4..13aaf54fad975 100644 --- a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/13_keyword_calculated_at_index.yml +++ b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/13_keyword_calculated_at_index.yml @@ -88,7 +88,7 @@ setup: - match: {hits.total.value: 6} - match: {hits.hits.0.fields.day_of_week: [Thursday] } - match: {hits.hits.0.fields.day_of_week_from_source: [Thursday] } - - match: {hits.hits.0.fields.day_of_week_letters: [T, h, u, r, s, d, a, y] } + - match: {hits.hits.0.fields.day_of_week_letters: [T, a, d, h, r, s, u, y] } - match: {hits.hits.0.fields.prefixed_node: [node_c] } --- diff --git a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/23_long_calculated_at_index.yml b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/23_long_calculated_at_index.yml index a6eff621344c1..765f875fa3b8c 100644 --- a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/23_long_calculated_at_index.yml +++ b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/23_long_calculated_at_index.yml @@ -17,6 +17,11 @@ setup: type: double node: type: keyword + random_long: + type: long + script: + source: | + emit(new Random().nextLong()); voltage_times_ten: type: long script: @@ -90,19 +95,55 @@ setup: sort: timestamp fields: - voltage_times_ten - - voltage_times_ten_no_dv - temperature_digits - match: {hits.total.value: 6} - match: {hits.hits.0.fields.voltage_times_ten: [40] } - - match: {hits.hits.0.fields.temperature_digits: [2, 0, 2] } + - match: {hits.hits.0.fields.temperature_digits: [0, 2, 2] } - match: {hits.hits.0.fields.voltage_times_ten: [40] } - - match: {hits.hits.0.fields.voltage_times_ten_no_dv: [40] } - match: {hits.hits.1.fields.voltage_times_ten: [42] } - match: {hits.hits.2.fields.voltage_times_ten: [56] } - match: {hits.hits.3.fields.voltage_times_ten: [51] } - match: {hits.hits.4.fields.voltage_times_ten: [58] } - match: {hits.hits.5.fields.voltage_times_ten: [52] } +--- +"script runs at index time": + - do: + search: + index: sensor + body: + sort: timestamp + fields: + - random_long + - match: {hits.total.value: 6} + - set: { hits.hits.0.fields.random_long.0: random_value } + + - do: + search: + index: sensor + body: + query: + match: + random_long: $random_value + aggs: + random_value: + terms: + field: random_long + - match: {hits.total.value: 1} + - match: {aggregations.random_value.buckets.0.key: $random_value} + - match: {aggregations.random_value.buckets.0.doc_count: 1} + +--- +"fetch fields no doc_values": + - do: + catch: bad_request + search: + index: sensor + body: + sort: timestamp + fields: + - voltage_times_ten_no_dv + --- "docvalue_fields": - do: diff --git a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/33_double_calculated_at_index.yml b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/33_double_calculated_at_index.yml index 15a8022f3c1b1..0bf642f068a29 100644 --- a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/33_double_calculated_at_index.yml +++ b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/33_double_calculated_at_index.yml @@ -17,6 +17,11 @@ setup: type: double node: type: keyword + random_double: + type: double + script: + source: | + emit(new Random().nextDouble()); voltage_percent: type: double script: @@ -88,18 +93,55 @@ setup: index: sensor body: sort: timestamp - fields: [voltage_percent, voltage_percent_no_dv, voltage_sqrts] + fields: [voltage_percent, voltage_sqrts] - match: {hits.total.value: 6} - match: {hits.hits.0.fields.voltage_percent: [0.6896551724137931] } - # Scripts that scripts that emit multiple values are supported - - match: {hits.hits.0.fields.voltage_sqrts: [4.0, 2.0, 1.4142135623730951] } + # Test that scripts that emit multiple values are supported and their results are sorted + - match: {hits.hits.0.fields.voltage_sqrts: [1.4142135623730951, 2.0, 4.0] } - match: {hits.hits.1.fields.voltage_percent: [0.7241379310344828] } - - match: {hits.hits.1.fields.voltage_percent_no_dv: [0.7241379310344828] } - match: {hits.hits.2.fields.voltage_percent: [0.9655172413793103] } - match: {hits.hits.3.fields.voltage_percent: [0.8793103448275862] } - match: {hits.hits.4.fields.voltage_percent: [1.0] } - match: {hits.hits.5.fields.voltage_percent: [0.896551724137931] } +--- +"script runs at index time": + - do: + search: + index: sensor + body: + sort: timestamp + fields: + - random_double + - match: {hits.total.value: 6} + - set: { hits.hits.0.fields.random_double.0: random_value } + + - do: + search: + index: sensor + body: + query: + match: + random_double: $random_value + aggs: + random_value: + terms: + field: random_double + - match: {hits.total.value: 1} + - match: {aggregations.random_value.buckets.0.key: $random_value} + - match: {aggregations.random_value.buckets.0.doc_count: 1} + +--- +"fetch fields no doc values": + - do: + catch: bad_request + search: + index: sensor + body: + sort: timestamp + fields: + - voltage_percent_no_dv + --- "docvalue_fields": - do: @@ -110,7 +152,7 @@ setup: docvalue_fields: [voltage_percent, voltage_sqrts] - match: {hits.total.value: 6} - match: {hits.hits.0.fields.voltage_percent: [0.6896551724137931] } - # Scripts that scripts that emit multiple values are supported and their results are sorted + # Test that scripts that emit multiple values are supported and their results are sorted - match: {hits.hits.0.fields.voltage_sqrts: [1.4142135623730951, 2.0, 4.0] } - match: {hits.hits.1.fields.voltage_percent: [0.7241379310344828] } - match: {hits.hits.2.fields.voltage_percent: [0.9655172413793103] } diff --git a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/43_date_calculated_at_index.yml b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/43_date_calculated_at_index.yml index 0f5ddd1e1b581..c56d314b5317e 100644 --- a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/43_date_calculated_at_index.yml +++ b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/43_date_calculated_at_index.yml @@ -60,6 +60,11 @@ setup: type: double node: type: keyword + ingest_time: + type: date + script: + source: | + emit(new Date().getTime()); - do: bulk: @@ -125,6 +130,27 @@ setup: - 2018-01-24T17:41:34.000Z - match: {hits.hits.0.fields.formatted_tomorrow: [2018-01-19] } +--- +"script runs at index time": + - do: + search: + index: sensor + body: + sort: timestamp + fields: + - ingest_time + - match: {hits.total.value: 6} + - set: { hits.hits.0.fields.ingest_time.0: ingest_time } + + - do: + search: + index: sensor + body: + query: + match: + ingest_time: $ingest_time + - gt: {hits.total.value: 0} + --- "docvalue_fields": - do: diff --git a/server/src/main/java/org/elasticsearch/index/mapper/BooleanFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/BooleanFieldMapper.java index 8100b83463c93..2c438b8f62290 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/BooleanFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/BooleanFieldMapper.java @@ -40,6 +40,7 @@ import org.elasticsearch.script.field.BooleanDocValuesField; import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; +import org.elasticsearch.search.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.xcontent.XContentBuilder; @@ -238,7 +239,11 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); } if (this.scriptValues != null) { - return FieldValues.valueFetcher(this.scriptValues, context); + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } return sourceValueFetcher(context.isSourceEnabled() ? context.sourcePath(name()) : Collections.emptySet()); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java index 6d04926d865a1..15201d6626ebf 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java @@ -53,6 +53,7 @@ import org.elasticsearch.script.field.DateNanosDocValuesField; import org.elasticsearch.script.field.ToScriptFieldFactory; import org.elasticsearch.search.DocValueFormat; +import org.elasticsearch.search.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.runtime.LongScriptFieldDistanceFeatureQuery; @@ -548,7 +549,11 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) ? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale()) : defaultFormatter; if (scriptValues != null) { - return FieldValues.valueFetcher(scriptValues, v -> format((long) v, formatter), context); + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } return new SourceValueFetcher(name(), context, nullValue) { @Override diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index b71a33976d72d..2fe7dc490919c 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -27,7 +27,6 @@ import org.elasticsearch.common.geo.GeoFormatterFactory; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoUtils; -import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.SimpleVectorTileFormatter; import org.elasticsearch.common.unit.DistanceUnit; @@ -49,6 +48,7 @@ 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.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.runtime.GeoPointScriptFieldDistanceFeatureQuery; @@ -419,8 +419,11 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) if (scriptValues == null) { return super.valueFetcher(context, format); } - Function, List> formatter = getFormatter(format != null ? format : GeometryFormatterFactory.GEOJSON); - return FieldValues.valueListFetcher(scriptValues, formatter, context); + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } @Override diff --git a/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java index 3ded3d2699b21..49cd196006a70 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java @@ -41,6 +41,7 @@ import org.elasticsearch.script.field.IpDocValuesField; import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; +import org.elasticsearch.search.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; @@ -285,7 +286,11 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); } if (scriptValues != null) { - return FieldValues.valueFetcher(scriptValues, v -> InetAddresses.toAddrString((InetAddress) v), context); + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } return new SourceValueFetcher(name(), context, nullValue) { @Override diff --git a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java index df308a4bf983c..c77e2d340210a 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java @@ -59,6 +59,7 @@ import org.elasticsearch.script.StringFieldScript; import org.elasticsearch.script.field.KeywordDocValuesField; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; +import org.elasticsearch.search.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.runtime.StringScriptFieldFuzzyQuery; @@ -843,7 +844,11 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); } if (this.scriptValues != null) { - return FieldValues.valueFetcher(this.scriptValues, context); + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } return sourceValueFetcher(context.isSourceEnabled() ? context.sourcePath(name()) : Collections.emptySet()); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java index 078faa25938f5..1cc26c18e2440 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java @@ -60,6 +60,7 @@ import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType; import org.elasticsearch.search.aggregations.support.ValuesSourceType; +import org.elasticsearch.search.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.lookup.SourceProvider; @@ -1965,7 +1966,12 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); } if (this.scriptValues != null) { - return FieldValues.valueFetcher(this.scriptValues, context); + + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } return sourceValueFetcher(context.isSourceEnabled() ? context.sourcePath(name()) : Collections.emptySet()); } diff --git a/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java b/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java index ceed4f48e7711..0133fe3ea0de6 100644 --- a/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java +++ b/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java @@ -10,14 +10,8 @@ package org.elasticsearch.search.lookup; import org.apache.lucene.index.LeafReaderContext; -import org.elasticsearch.index.mapper.ValueFetcher; -import org.elasticsearch.index.query.SearchExecutionContext; -import org.elasticsearch.search.fetch.StoredFieldsSpec; -import java.util.ArrayList; -import java.util.List; import java.util.function.Consumer; -import java.util.function.Function; /** * Represents values for a given document @@ -32,86 +26,4 @@ public interface FieldValues { * @param consumer called with each document value */ void valuesForDoc(SearchLookup lookup, LeafReaderContext ctx, int doc, Consumer consumer); - - /** - * Creates a {@link ValueFetcher} that fetches values from a {@link FieldValues} instance - * @param fieldValues the source of the values - * @param context the search execution context - * @return the value fetcher - */ - static ValueFetcher valueFetcher(FieldValues fieldValues, SearchExecutionContext context) { - return valueFetcher(fieldValues, v -> v, context); - } - - /** - * Creates a {@link ValueFetcher} that fetches values from a {@link FieldValues} instance - * @param fieldValues the source of the values - * @param formatter a function to format the values - * @param context the search execution context - * @return the value fetcher - */ - static ValueFetcher valueFetcher(FieldValues fieldValues, Function formatter, SearchExecutionContext context) { - return new ValueFetcher() { - LeafReaderContext ctx; - - @Override - public void setNextReader(LeafReaderContext context) { - this.ctx = context; - } - - @Override - public List fetchValues(Source lookup, int doc, List ignoredValues) { - List values = new ArrayList<>(); - try { - fieldValues.valuesForDoc(context.lookup(), ctx, doc, v -> values.add(formatter.apply(v))); - } catch (Exception e) { - ignoredValues.addAll(values); - } - return values; - } - - @Override - public StoredFieldsSpec storedFieldsSpec() { - return StoredFieldsSpec.NEEDS_SOURCE; // TODO can we get more information from the script - } - }; - } - - /** - * Creates a {@link ValueFetcher} that fetches values from a {@link FieldValues} instance - * @param fieldValues the source of the values - * @param formatter a function to format the list values - * @param context the search execution context - * @return the value fetcher - */ - static ValueFetcher valueListFetcher( - FieldValues fieldValues, - Function, List> formatter, - SearchExecutionContext context - ) { - return new ValueFetcher() { - LeafReaderContext ctx; - - @Override - public void setNextReader(LeafReaderContext context) { - this.ctx = context; - } - - @Override - public List fetchValues(Source source, int doc, List ignoredValues) { - List values = new ArrayList<>(); - try { - fieldValues.valuesForDoc(context.lookup(), ctx, doc, values::add); - } catch (Exception e) { - ignoredValues.addAll(values); - } - return formatter.apply(values); - } - - @Override - public StoredFieldsSpec storedFieldsSpec() { - return StoredFieldsSpec.NEEDS_SOURCE; // TODO can we get more info from the script? - } - }; - } } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java index 62e68bfdb425c..5ae99c552c630 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java @@ -34,6 +34,7 @@ import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper; import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.DocValueFetcher; import org.elasticsearch.index.mapper.DocumentParserContext; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.GeoShapeIndexer; @@ -59,6 +60,7 @@ import org.elasticsearch.script.field.AbstractScriptFieldFactory; import org.elasticsearch.script.field.DocValuesScriptFieldFactory; import org.elasticsearch.script.field.Field; +import org.elasticsearch.search.fetch.StoredFieldsSpec; import org.elasticsearch.search.lookup.FieldValues; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues; @@ -293,8 +295,11 @@ public List parseStoredValues(List storedValues) { }; } if (scriptValues != null) { - Function, List> formatter = getFormatter(format != null ? format : GeometryFormatterFactory.GEOJSON); - return FieldValues.valueListFetcher(scriptValues, formatter, context); + return new DocValueFetcher( + docValueFormat(format, null), + context.getForField(this, FielddataOperation.SEARCH), + StoredFieldsSpec.NO_REQUIREMENTS + ); } return super.valueFetcher(context, format); }