From edb42690bc0bf9e49e0da25dea5aaa3aea78b948 Mon Sep 17 00:00:00 2001 From: Luca Cavanna Date: Tue, 23 Mar 2021 10:57:44 +0100 Subject: [PATCH] Split RuntimeFieldType from corresponding MappedFieldType (#70695) So far the runtime section supports only leaf field types, hence the internal representation is based on `RuntimeFieldType` that extends directly `MappedFieldType`. This is straightforward but it is limiting for e.g. an alias field that points to another field, or for object fields that are not queryable directly, hence should not be a MappedFieldType, yet their subfields do. This commit makes `RuntimeFieldType` an interface, effectively splitting the definition of a runtime fields as defined and returned in the mappings, from its internal representation in terms of `MappedFieldType`. The existing runtime script field types still extend `MappedFieldType` and now also implement the new interface, which makes the change rather simple. --- .../join/mapper/ParentJoinFieldMapper.java | 2 +- ...TransportFieldCapabilitiesIndexAction.java | 1 + .../index/mapper/DocumentParser.java | 6 +- .../index/mapper/FieldMapper.java | 15 +- .../index/mapper/FieldTypeLookup.java | 3 +- .../index/mapper/MetadataFieldMapper.java | 3 +- .../index/mapper/RuntimeFieldType.java | 177 +++--------------- .../index/mapper/TextFieldMapper.java | 3 +- .../index/query/SearchExecutionContext.java | 15 +- .../mapper/AbstractScriptFieldType.java | 158 +++++++++++++++- .../mapper/BooleanScriptFieldType.java | 18 +- .../mapper/DateScriptFieldType.java | 21 +-- .../mapper/DoubleScriptFieldType.java | 18 +- .../mapper/GeoPointScriptFieldType.java | 16 +- .../mapper/IpScriptFieldType.java | 16 +- .../mapper/KeywordScriptFieldType.java | 18 +- .../mapper/LongScriptFieldType.java | 18 +- .../index/IndexSortSettingsTests.java | 18 +- .../FieldAliasMapperValidationTests.java | 2 +- .../index/mapper/MappingLookupTests.java | 2 +- .../index/mapper/RangeFieldMapperTests.java | 4 +- .../index/mapper/TestRuntimeField.java | 23 ++- .../query/SearchExecutionContextTests.java | 2 +- .../mapper/BooleanScriptFieldTypeTests.java | 2 +- .../mapper/DateScriptFieldTypeTests.java | 2 +- .../mapper/DoubleScriptFieldTypeTests.java | 2 +- .../mapper/GeoPointScriptFieldTypeTests.java | 2 +- .../mapper/IpScriptFieldTypeTests.java | 2 +- .../mapper/KeywordScriptFieldTypeTests.java | 2 +- .../mapper/LongScriptFieldTypeTests.java | 2 +- 30 files changed, 281 insertions(+), 292 deletions(-) diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java index 02ed3e95438c4..45a28add09651 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java @@ -273,7 +273,7 @@ public void parse(ParseContext context) throws IOException { } @Override - protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException { + protected void doXContentBody(XContentBuilder builder, Params params) throws IOException { builder.field("type", contentType()); builder.field("eager_global_ordinals", eagerGlobalOrdinals); builder.startObject("relations"); diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java index a21a039379739..88b87cd576229 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java @@ -128,6 +128,7 @@ private FieldCapabilitiesIndexResponse shardOperation(final FieldCapabilitiesInd // Check the ancestor of the field to find nested and object fields. // Runtime fields are excluded since they can override any path. + //TODO find a way to do this that does not require an instanceof check if (ft instanceof RuntimeFieldType == false) { int dotIndex = ft.name().lastIndexOf('.'); while (dotIndex > -1) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index a738a2791ab53..77317f8191f2a 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -801,14 +801,14 @@ private static Mapper getLeafMapper(final ParseContext context, String fieldPath = context.path().pathAsText(fieldName); RuntimeFieldType runtimeFieldType = context.root().getRuntimeFieldType(fieldPath); if (runtimeFieldType != null) { - return new NoOpFieldMapper(subfields[subfields.length - 1], runtimeFieldType); + return new NoOpFieldMapper(subfields[subfields.length - 1], runtimeFieldType.asMappedFieldType().name()); } return null; } private static class NoOpFieldMapper extends FieldMapper { - NoOpFieldMapper(String simpleName, RuntimeFieldType runtimeField) { - super(simpleName, new MappedFieldType(runtimeField.name(), false, false, false, TextSearchInfo.NONE, Collections.emptyMap()) { + NoOpFieldMapper(String simpleName, String fullName) { + super(simpleName, new MappedFieldType(fullName, false, false, false, TextSearchInfo.NONE, Collections.emptyMap()) { @Override public ValueFetcher valueFetcher(SearchExecutionContext context, String format) { throw new UnsupportedOperationException(); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java index 8851a442f9946..7c6914b28bde1 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -17,6 +17,7 @@ import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.ToXContentFragment; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.support.AbstractXContentParser; @@ -288,14 +289,13 @@ protected void checkIncomingMergeType(FieldMapper mergeWith) { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(simpleName()); - boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - doXContentBody(builder, includeDefaults, params); + doXContentBody(builder, params); return builder.endObject(); } - protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException { + protected void doXContentBody(XContentBuilder builder, Params params) throws IOException { builder.field("type", contentType()); - getMergeBuilder().toXContent(builder, includeDefaults); + getMergeBuilder().toXContent(builder, params); multiFields.toXContent(builder, params); copyTo.toXContent(builder, params); } @@ -856,7 +856,7 @@ void check() { /** * A Builder for a ParametrizedFieldMapper */ - public abstract static class Builder extends Mapper.Builder { + public abstract static class Builder extends Mapper.Builder implements ToXContentFragment { protected final MultiFields.Builder multiFieldsBuilder = new MultiFields.Builder(); protected final CopyTo.Builder copyTo = new CopyTo.Builder(); @@ -916,10 +916,13 @@ protected String buildFullName(ContentPath contentPath) { /** * Writes the current builder parameter values as XContent */ - public final void toXContent(XContentBuilder builder, boolean includeDefaults) throws IOException { + @Override + public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + boolean includeDefaults = params.paramAsBoolean("include_defaults", false); for (Parameter parameter : getParameters()) { parameter.toXContent(builder, includeDefaults); } + return builder; } /** diff --git a/server/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java b/server/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java index 162ca234e626a..0bc67b05c9fda 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java @@ -69,7 +69,8 @@ final class FieldTypeLookup { fullNameToFieldType.put(aliasName, fullNameToFieldType.get(path)); } - for (RuntimeFieldType runtimeFieldType : runtimeFieldTypes) { + for (RuntimeFieldType runtimeField : runtimeFieldTypes) { + MappedFieldType runtimeFieldType = runtimeField.asMappedFieldType(); //this will override concrete fields with runtime fields that have the same name fullNameToFieldType.put(runtimeFieldType.name(), runtimeFieldType); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MetadataFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/MetadataFieldMapper.java index 8dbaa74b4bfda..111bf99a005f6 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MetadataFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MetadataFieldMapper.java @@ -145,8 +145,7 @@ public final XContentBuilder toXContent(XContentBuilder builder, Params params) return builder; } builder.startObject(simpleName()); - boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - getMergeBuilder().toXContent(builder, includeDefaults); + getMergeBuilder().toXContent(builder, params); return builder.endObject(); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/RuntimeFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/RuntimeFieldType.java index 110a7adf83b20..5cc0b74515ea0 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/RuntimeFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/RuntimeFieldType.java @@ -8,54 +8,27 @@ package org.elasticsearch.index.mapper; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.search.MultiTermQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper; -import org.apache.lucene.search.spans.SpanQuery; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.CheckedBiConsumer; -import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.common.time.DateMathParser; -import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.xcontent.ToXContentFragment; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.index.query.SearchExecutionContext; import java.io.IOException; -import java.time.ZoneId; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.function.BiFunction; -import static org.elasticsearch.search.SearchService.ALLOW_EXPENSIVE_QUERIES; - /** - * Base implementation for a runtime field that can be defined as part of the runtime section of the index mappings + * Definition of a runtime field that can be defined as part of the runtime section of the index mappings */ -public abstract class RuntimeFieldType extends MappedFieldType implements ToXContentFragment { - - private final CheckedBiConsumer toXContent; - - protected RuntimeFieldType(String name, RuntimeFieldType.Builder builder) { - this(name, builder.meta(), builder::toXContent); - } - - protected RuntimeFieldType(String name, Map meta, CheckedBiConsumer toXContent) { - super(name, false, false, false, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta); - this.toXContent = toXContent; - } +public interface RuntimeFieldType extends ToXContentFragment { @Override - public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + default XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(name()); builder.field("type", typeName()); - boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - doXContentBody(builder, includeDefaults); + doXContentBody(builder, params); builder.endObject(); return builder; } @@ -63,125 +36,25 @@ public final XContentBuilder toXContent(XContentBuilder builder, Params params) /** * Prints out the parameters that subclasses expose */ - final void doXContentBody(XContentBuilder builder, boolean includeDefaults) throws IOException { - toXContent.accept(builder, includeDefaults); - } - - @Override - public final boolean isSearchable() { - return true; - } - - @Override - public final boolean isAggregatable() { - return true; - } - - @Override - public final Query rangeQuery( - Object lowerTerm, - Object upperTerm, - boolean includeLower, - boolean includeUpper, - ShapeRelation relation, - ZoneId timeZone, - DateMathParser parser, - SearchExecutionContext context - ) { - if (relation == ShapeRelation.DISJOINT) { - String message = "Runtime field [%s] of type [%s] does not support DISJOINT ranges"; - throw new IllegalArgumentException(String.format(Locale.ROOT, message, name(), typeName())); - } - return rangeQuery(lowerTerm, upperTerm, includeLower, includeUpper, timeZone, parser, context); - } - - protected abstract Query rangeQuery( - Object lowerTerm, - Object upperTerm, - boolean includeLower, - boolean includeUpper, - ZoneId timeZone, - DateMathParser parser, - SearchExecutionContext context - ); - - @Override - public Query fuzzyQuery( - Object value, - Fuzziness fuzziness, - int prefixLength, - int maxExpansions, - boolean transpositions, - SearchExecutionContext context - ) { - throw new IllegalArgumentException(unsupported("fuzzy", "keyword and text")); - } - - @Override - public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, SearchExecutionContext context) { - throw new IllegalArgumentException(unsupported("prefix", "keyword, text and wildcard")); - } - - @Override - public Query wildcardQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, SearchExecutionContext context) { - throw new IllegalArgumentException(unsupported("wildcard", "keyword, text and wildcard")); - } + void doXContentBody(XContentBuilder builder, Params params) throws IOException; - @Override - public Query regexpQuery( - String value, - int syntaxFlags, - int matchFlags, - int maxDeterminizedStates, - MultiTermQuery.RewriteMethod method, - SearchExecutionContext context - ) { - throw new IllegalArgumentException(unsupported("regexp", "keyword and text")); - } - - @Override - public Query phraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) { - throw new IllegalArgumentException(unsupported("phrase", "text")); - } - - @Override - public Query multiPhraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) { - throw new IllegalArgumentException(unsupported("phrase", "text")); - } - - @Override - public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions) { - throw new IllegalArgumentException(unsupported("phrase prefix", "text")); - } - - @Override - public SpanQuery spanPrefixQuery(String value, SpanMultiTermQueryWrapper.SpanRewriteMethod method, SearchExecutionContext context) { - throw new IllegalArgumentException(unsupported("span prefix", "text")); - } - - private String unsupported(String query, String supported) { - return String.format( - Locale.ROOT, - "Can only use %s queries on %s fields - not on [%s] which is a runtime field of type [%s]", - query, - supported, - name(), - typeName() - ); - } + /** + * Exposes the name of the runtime field + * @return name of the field + */ + String name(); - protected final void checkAllowExpensiveQueries(SearchExecutionContext context) { - if (context.allowExpensiveQueries() == false) { - throw new ElasticsearchException( - "queries cannot be executed against runtime fields while [" + ALLOW_EXPENSIVE_QUERIES.getKey() + "] is set to [false]." - ); - } - } + /** + * Exposes the type of the runtime field + * @return type of the field + */ + String typeName(); - @Override - public final ValueFetcher valueFetcher(SearchExecutionContext context, String format) { - return new DocValueFetcher(docValueFormat(format, null), context.getForField(this)); - } + /** + * Exposes the {@link MappedFieldType} backing this runtime field, used to execute queries, run aggs etc. + * @return the {@link MappedFieldType} backing this runtime field + */ + MappedFieldType asMappedFieldType(); /** * For runtime fields the {@link RuntimeFieldType.Parser} returns directly the {@link MappedFieldType}. @@ -191,7 +64,7 @@ public final ValueFetcher valueFetcher(SearchExecutionContext context, String fo * {@link RuntimeFieldType.Builder#parse(String, Mapper.TypeParser.ParserContext, Map)} and returns the corresponding * {@link MappedFieldType}. */ - public abstract static class Builder extends FieldMapper.Builder { + abstract class Builder extends FieldMapper.Builder { final FieldMapper.Parameter> meta = FieldMapper.Parameter.metaParam(); protected Builder(String name) { @@ -236,7 +109,7 @@ private void validate() { * Parser for a runtime field. Creates the appropriate {@link RuntimeFieldType} for a runtime field, * as defined in the runtime section of the index mappings. */ - public static final class Parser { + final class Parser { private final BiFunction builderFunction; public Parser(BiFunction builderFunction) { @@ -261,9 +134,9 @@ RuntimeFieldType parse(String name, Map node, Mapper.TypeParser. * translated to the removal of such runtime field * @return the parsed runtime fields */ - public static Map parseRuntimeFields(Map node, - Mapper.TypeParser.ParserContext parserContext, - boolean supportsRemoval) { + static Map parseRuntimeFields(Map node, + Mapper.TypeParser.ParserContext parserContext, + boolean supportsRemoval) { Map runtimeFields = new HashMap<>(); Iterator> iterator = node.entrySet().iterator(); while (iterator.hasNext()) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java index 915694169265b..77e93e4e2f016 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java @@ -958,8 +958,9 @@ public static Query createPhrasePrefixQuery(TokenStream stream, String field, in } @Override - protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException { + protected void doXContentBody(XContentBuilder builder, Params params) throws IOException { // this is a pain, but we have to do this to maintain BWC + boolean includeDefaults = params.paramAsBoolean("include_defaults", false); builder.field("type", contentType()); this.builder.index.toXContent(builder, includeDefaults); this.builder.store.toXContent(builder, includeDefaults); diff --git a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java index 740df6382b20a..6149124b996d7 100644 --- a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java @@ -106,7 +106,7 @@ public class SearchExecutionContext extends QueryRewriteContext { private boolean mapUnmappedFieldAsString; private NestedScope nestedScope; private final ValuesSourceRegistry valuesSourceRegistry; - private final Map runtimeMappings; + private final Map runtimeMappings; /** * Build a {@linkplain SearchExecutionContext}. @@ -199,7 +199,7 @@ private SearchExecutionContext(int shardId, Index fullyQualifiedIndex, BooleanSupplier allowExpensiveQueries, ValuesSourceRegistry valuesSourceRegistry, - Map runtimeMappings) { + Map runtimeMappings) { super(xContentRegistry, namedWriteableRegistry, client, nowInMillis); this.shardId = shardId; this.shardRequestIndex = shardRequestIndex; @@ -608,11 +608,18 @@ public Index getFullyQualifiedIndex() { return fullyQualifiedIndex; } - private static Map parseRuntimeMappings(Map runtimeMappings, MapperService mapperService) { + private static Map parseRuntimeMappings(Map runtimeMappings, MapperService mapperService) { if (runtimeMappings.isEmpty()) { return Collections.emptyMap(); } - return RuntimeFieldType.parseRuntimeFields(new HashMap<>(runtimeMappings), mapperService.parserContext(), false); + Map runtimeFields = RuntimeFieldType.parseRuntimeFields(new HashMap<>(runtimeMappings), + mapperService.parserContext(), false); + Map runtimeFieldTypes = new HashMap<>(); + for (RuntimeFieldType runtimeFieldType : runtimeFields.values()) { + MappedFieldType fieldType = runtimeFieldType.asMappedFieldType(); + runtimeFieldTypes.put(fieldType.name(), fieldType); + } + return Collections.unmodifiableMap(runtimeFieldTypes); } /** diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/AbstractScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/AbstractScriptFieldType.java index fd6fbb974a35b..13b90d55b0d31 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/AbstractScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/AbstractScriptFieldType.java @@ -8,48 +8,186 @@ package org.elasticsearch.runtimefields.mapper; -import org.elasticsearch.common.CheckedBiConsumer; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.search.MultiTermQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper; +import org.apache.lucene.search.spans.SpanQuery; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.TriFunction; +import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.time.DateMathParser; +import org.elasticsearch.common.unit.Fuzziness; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.mapper.DocValueFetcher; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.RuntimeFieldType; +import org.elasticsearch.index.mapper.TextSearchInfo; +import org.elasticsearch.index.mapper.ValueFetcher; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptType; import org.elasticsearch.search.lookup.SearchLookup; import java.io.IOException; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.function.Function; +import static org.elasticsearch.search.SearchService.ALLOW_EXPENSIVE_QUERIES; + /** * Abstract base {@linkplain MappedFieldType} for runtime fields based on a script. */ -abstract class AbstractScriptFieldType extends RuntimeFieldType { +abstract class AbstractScriptFieldType extends MappedFieldType implements RuntimeFieldType { protected final Script script; private final TriFunction, SearchLookup, LeafFactory> factory; - - AbstractScriptFieldType(String name, TriFunction, SearchLookup, LeafFactory> factory, Builder builder) { - super(name, builder); - this.factory = factory; - this.script = builder.getScript(); - } + private final ToXContent toXContent; AbstractScriptFieldType( String name, TriFunction, SearchLookup, LeafFactory> factory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { - super(name, meta, toXContent); + super(name, false, false, false, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta); this.factory = factory; this.script = script; + this.toXContent = toXContent; + } + + @Override + public final MappedFieldType asMappedFieldType() { + return this; + } + + @Override + public final void doXContentBody(XContentBuilder builder, Params params) throws IOException { + toXContent.toXContent(builder, params); + } + + @Override + public final boolean isSearchable() { + return true; + } + + @Override + public final boolean isAggregatable() { + return true; + } + + @Override + public final Query rangeQuery( + Object lowerTerm, + Object upperTerm, + boolean includeLower, + boolean includeUpper, + ShapeRelation relation, + ZoneId timeZone, + DateMathParser parser, + SearchExecutionContext context + ) { + if (relation == ShapeRelation.DISJOINT) { + String message = "Runtime field [%s] of type [%s] does not support DISJOINT ranges"; + throw new IllegalArgumentException(String.format(Locale.ROOT, message, name(), typeName())); + } + return rangeQuery(lowerTerm, upperTerm, includeLower, includeUpper, timeZone, parser, context); + } + + protected abstract Query rangeQuery( + Object lowerTerm, + Object upperTerm, + boolean includeLower, + boolean includeUpper, + ZoneId timeZone, + DateMathParser parser, + SearchExecutionContext context + ); + + @Override + public Query fuzzyQuery( + Object value, + Fuzziness fuzziness, + int prefixLength, + int maxExpansions, + boolean transpositions, + SearchExecutionContext context + ) { + throw new IllegalArgumentException(unsupported("fuzzy", "keyword and text")); + } + + @Override + public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, SearchExecutionContext context) { + throw new IllegalArgumentException(unsupported("prefix", "keyword, text and wildcard")); + } + + @Override + public Query wildcardQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, SearchExecutionContext context) { + throw new IllegalArgumentException(unsupported("wildcard", "keyword, text and wildcard")); + } + + @Override + public Query regexpQuery( + String value, + int syntaxFlags, + int matchFlags, + int maxDeterminizedStates, + MultiTermQuery.RewriteMethod method, + SearchExecutionContext context + ) { + throw new IllegalArgumentException(unsupported("regexp", "keyword and text")); + } + + @Override + public Query phraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) { + throw new IllegalArgumentException(unsupported("phrase", "text")); + } + + @Override + public Query multiPhraseQuery(TokenStream stream, int slop, boolean enablePositionIncrements) { + throw new IllegalArgumentException(unsupported("phrase", "text")); + } + + @Override + public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions) { + throw new IllegalArgumentException(unsupported("phrase prefix", "text")); + } + + @Override + public SpanQuery spanPrefixQuery(String value, SpanMultiTermQueryWrapper.SpanRewriteMethod method, SearchExecutionContext context) { + throw new IllegalArgumentException(unsupported("span prefix", "text")); + } + + private String unsupported(String query, String supported) { + return String.format( + Locale.ROOT, + "Can only use %s queries on %s fields - not on [%s] which is a runtime field of type [%s]", + query, + supported, + name(), + typeName() + ); + } + + protected final void checkAllowExpensiveQueries(SearchExecutionContext context) { + if (context.allowExpensiveQueries() == false) { + throw new ElasticsearchException( + "queries cannot be executed against runtime fields while [" + ALLOW_EXPENSIVE_QUERIES.getKey() + "] is set to [false]." + ); + } + } + + @Override + public final ValueFetcher valueFetcher(SearchExecutionContext context, String format) { + return new DocValueFetcher(docValueFormat(format, null), context.getForField(this)); } /** diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldType.java index faca2923e8a95..6ce783c2ed53d 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldType.java @@ -12,11 +12,10 @@ import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.Booleans; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.Strings; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.time.DateMathParser; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.index.mapper.BooleanFieldMapper; import org.elasticsearch.index.mapper.RuntimeFieldType; import org.elasticsearch.index.query.SearchExecutionContext; @@ -27,7 +26,6 @@ import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.time.ZoneId; import java.util.Collection; import java.util.Collections; @@ -38,21 +36,17 @@ public final class BooleanScriptFieldType extends AbstractScriptFieldType new Builder(name) { @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { if (script.get() == null) { - return new BooleanScriptFieldType(name, BooleanFieldScript.PARSE_FROM_SOURCE, this); + return new BooleanScriptFieldType(name, BooleanFieldScript.PARSE_FROM_SOURCE, getScript(), meta(), this); } BooleanFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), BooleanFieldScript.CONTEXT); - return new BooleanScriptFieldType(name, factory, this); + return new BooleanScriptFieldType(name, factory, getScript(), meta(), this); } }); - private BooleanScriptFieldType(String name, BooleanFieldScript.Factory scriptFactory, Builder builder) { - super(name, scriptFactory::newFactory, builder); - } - public BooleanScriptFieldType(String name) { - this(name, BooleanFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, includeDefaults) -> {}); + this(name, BooleanFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder); } BooleanScriptFieldType( @@ -60,7 +54,7 @@ public BooleanScriptFieldType(String name) { BooleanFieldScript.Factory scriptFactory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, scriptFactory::newFactory, script, meta, toXContent); } diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldType.java index 5418a76793873..0e1365658a70c 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldType.java @@ -11,14 +11,13 @@ import com.carrotsearch.hppc.LongHashSet; import com.carrotsearch.hppc.LongSet; import org.apache.lucene.search.Query; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.common.time.DateMathParser; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.LocaleUtils; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.index.mapper.DateFieldMapper; import org.elasticsearch.index.mapper.DateFieldMapper.DateFieldType; import org.elasticsearch.index.mapper.DateFieldMapper.Resolution; @@ -35,7 +34,6 @@ import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.ArrayList; @@ -81,32 +79,27 @@ protected List> getParameters() { } @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { String pattern = format.getValue() == null ? DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern() : format.getValue(); Locale locale = this.locale.getValue() == null ? Locale.ROOT : this.locale.getValue(); DateFormatter dateTimeFormatter = DateFormatter.forPattern(pattern).withLocale(locale); if (script.get() == null) { - return new DateScriptFieldType(name, DateFieldScript.PARSE_FROM_SOURCE, dateTimeFormatter, this); + return new DateScriptFieldType(name, DateFieldScript.PARSE_FROM_SOURCE, dateTimeFormatter, getScript(), meta(), this); } DateFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), DateFieldScript.CONTEXT); - return new DateScriptFieldType(name, factory, dateTimeFormatter, this); + return new DateScriptFieldType(name, factory, dateTimeFormatter, getScript(), meta(), this); } }); private final DateFormatter dateTimeFormatter; private final DateMathParser dateMathParser; - private DateScriptFieldType(String name, DateFieldScript.Factory scriptFactory, DateFormatter dateTimeFormatter, Builder builder) { - super(name, (n, params, ctx) -> scriptFactory.newFactory(n, params, ctx, dateTimeFormatter), builder); - this.dateTimeFormatter = dateTimeFormatter; - this.dateMathParser = dateTimeFormatter.toDateMathParser(); - } - public DateScriptFieldType(String name, DateFormatter dateTimeFormatter) { - this(name, DateFieldScript.PARSE_FROM_SOURCE, dateTimeFormatter, null, Collections.emptyMap(), (builder, includeDefaults) -> { + this(name, DateFieldScript.PARSE_FROM_SOURCE, dateTimeFormatter, null, Collections.emptyMap(), (builder, params) -> { if (DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern().equals(dateTimeFormatter.pattern()) == false) { builder.field("format", dateTimeFormatter.pattern()); } + return builder; }); } @@ -116,7 +109,7 @@ public DateScriptFieldType(String name, DateFormatter dateTimeFormatter) { DateFormatter dateTimeFormatter, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, (n, params, ctx) -> scriptFactory.newFactory(n, params, ctx, dateTimeFormatter), script, meta, toXContent); this.dateTimeFormatter = dateTimeFormatter; diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldType.java index 926725c97e1a1..5dd333760fbb4 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldType.java @@ -11,10 +11,9 @@ import com.carrotsearch.hppc.LongHashSet; import com.carrotsearch.hppc.LongSet; import org.apache.lucene.search.Query; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.time.DateMathParser; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType; import org.elasticsearch.index.mapper.RuntimeFieldType; import org.elasticsearch.index.query.SearchExecutionContext; @@ -27,7 +26,6 @@ import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.time.ZoneId; import java.util.Collection; import java.util.Collections; @@ -38,21 +36,17 @@ public final class DoubleScriptFieldType extends AbstractScriptFieldType new Builder(name) { @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { if (script.get() == null) { - return new DoubleScriptFieldType(name, DoubleFieldScript.PARSE_FROM_SOURCE, this); + return new DoubleScriptFieldType(name, DoubleFieldScript.PARSE_FROM_SOURCE, getScript(), meta(), this); } DoubleFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), DoubleFieldScript.CONTEXT); - return new DoubleScriptFieldType(name, factory, this); + return new DoubleScriptFieldType(name, factory, getScript(), meta(), this); } }); - private DoubleScriptFieldType(String name, DoubleFieldScript.Factory scriptFactory, Builder builder) { - super(name, scriptFactory::newFactory, builder); - } - public DoubleScriptFieldType(String name) { - this(name, DoubleFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, includeDefaults) -> {}); + this(name, DoubleFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder); } DoubleScriptFieldType( @@ -60,7 +54,7 @@ public DoubleScriptFieldType(String name) { DoubleFieldScript.Factory scriptFactory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, scriptFactory::newFactory, script, meta, toXContent); } diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldType.java index 537136c163115..ee18642f2c383 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldType.java @@ -12,14 +12,13 @@ import org.apache.lucene.geo.Point; import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoShapeUtils; import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.time.DateMathParser; import org.elasticsearch.common.unit.DistanceUnit; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.geometry.Geometry; import org.elasticsearch.index.mapper.GeoPointFieldMapper; import org.elasticsearch.index.mapper.GeoShapeQueryable; @@ -32,7 +31,6 @@ import org.elasticsearch.script.Script; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.time.ZoneId; import java.util.Arrays; import java.util.Map; @@ -42,25 +40,21 @@ public final class GeoPointScriptFieldType extends AbstractScriptFieldType new Builder(name) { @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { if (script.get() == null) { - return new GeoPointScriptFieldType(name, GeoPointFieldScript.PARSE_FROM_SOURCE, this); + return new GeoPointScriptFieldType(name, GeoPointFieldScript.PARSE_FROM_SOURCE, getScript(), meta(), this); } GeoPointFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), GeoPointFieldScript.CONTEXT); - return new GeoPointScriptFieldType(name, factory, this); + return new GeoPointScriptFieldType(name, factory, getScript(), meta(), this); } }); - private GeoPointScriptFieldType(String name, GeoPointFieldScript.Factory scriptFactory, Builder builder) { - super(name, scriptFactory::newFactory, builder); - } - GeoPointScriptFieldType( String name, GeoPointFieldScript.Factory scriptFactory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, scriptFactory::newFactory, script, meta, toXContent); } diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldType.java index c36b3217c2fad..5a9830bfda9bd 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldType.java @@ -13,14 +13,13 @@ import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.network.InetAddresses; import org.elasticsearch.common.time.DateMathParser; import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.BytesRefHash; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.index.mapper.IpFieldMapper; import org.elasticsearch.index.mapper.RuntimeFieldType; import org.elasticsearch.index.query.SearchExecutionContext; @@ -33,7 +32,6 @@ import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.net.InetAddress; import java.time.ZoneId; import java.util.ArrayList; @@ -47,25 +45,21 @@ public final class IpScriptFieldType extends AbstractScriptFieldType new Builder(name) { @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { if (script.get() == null) { - return new IpScriptFieldType(name, IpFieldScript.PARSE_FROM_SOURCE, this); + return new IpScriptFieldType(name, IpFieldScript.PARSE_FROM_SOURCE, getScript(), meta(), this); } IpFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), IpFieldScript.CONTEXT); - return new IpScriptFieldType(name, factory, this); + return new IpScriptFieldType(name, factory, getScript(), meta(), this); } }); - private IpScriptFieldType(String name, IpFieldScript.Factory scriptFactory, Builder builder) { - super(name, scriptFactory::newFactory, builder); - } - IpScriptFieldType( String name, IpFieldScript.Factory scriptFactory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, scriptFactory::newFactory, script, meta, toXContent); } diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldType.java index f93d3d15e3163..22356aebfdd1e 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldType.java @@ -11,11 +11,10 @@ import org.apache.lucene.search.MultiTermQuery.RewriteMethod; import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.time.DateMathParser; import org.elasticsearch.common.unit.Fuzziness; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.index.mapper.KeywordFieldMapper; import org.elasticsearch.index.mapper.RuntimeFieldType; import org.elasticsearch.index.query.SearchExecutionContext; @@ -31,7 +30,6 @@ import org.elasticsearch.script.Script; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.time.ZoneId; import java.util.Collection; import java.util.Collections; @@ -46,21 +44,17 @@ public final class KeywordScriptFieldType extends AbstractScriptFieldType new Builder(name) { @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { if (script.get() == null) { - return new KeywordScriptFieldType(name, StringFieldScript.PARSE_FROM_SOURCE, this); + return new KeywordScriptFieldType(name, StringFieldScript.PARSE_FROM_SOURCE, getScript(), meta(), this); } StringFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), StringFieldScript.CONTEXT); - return new KeywordScriptFieldType(name, factory, this); + return new KeywordScriptFieldType(name, factory, getScript(), meta(), this); } }); public KeywordScriptFieldType(String name) { - this(name, StringFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, includeDefaults) -> {}); - } - - private KeywordScriptFieldType(String name, StringFieldScript.Factory scriptFactory, Builder builder) { - super(name, scriptFactory::newFactory, builder); + this(name, StringFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder); } KeywordScriptFieldType( @@ -68,7 +62,7 @@ private KeywordScriptFieldType(String name, StringFieldScript.Factory scriptFact StringFieldScript.Factory scriptFactory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, scriptFactory::newFactory, script, meta, toXContent); } diff --git a/server/src/main/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldType.java b/server/src/main/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldType.java index 16f07c252662a..10df02af16a72 100644 --- a/server/src/main/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldType.java +++ b/server/src/main/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldType.java @@ -11,10 +11,9 @@ import com.carrotsearch.hppc.LongHashSet; import com.carrotsearch.hppc.LongSet; import org.apache.lucene.search.Query; -import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.time.DateMathParser; -import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType; import org.elasticsearch.index.mapper.RuntimeFieldType; import org.elasticsearch.index.query.SearchExecutionContext; @@ -27,7 +26,6 @@ import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.lookup.SearchLookup; -import java.io.IOException; import java.time.ZoneId; import java.util.Collection; import java.util.Collections; @@ -38,21 +36,17 @@ public final class LongScriptFieldType extends AbstractScriptFieldType new Builder(name) { @Override - protected AbstractScriptFieldType buildFieldType() { + protected RuntimeFieldType buildFieldType() { if (script.get() == null) { - return new LongScriptFieldType(name, LongFieldScript.PARSE_FROM_SOURCE, this); + return new LongScriptFieldType(name, LongFieldScript.PARSE_FROM_SOURCE, getScript(), meta(), this); } LongFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.getValue(), LongFieldScript.CONTEXT); - return new LongScriptFieldType(name, factory, this); + return new LongScriptFieldType(name, factory, getScript(), meta(), this); } }); public LongScriptFieldType(String name) { - this(name, LongFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, includeDefaults) -> {}); - } - - private LongScriptFieldType(String name, LongFieldScript.Factory scriptFactory, Builder builder) { - super(name, scriptFactory::newFactory, builder); + this(name, LongFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder); } LongScriptFieldType( @@ -60,7 +54,7 @@ private LongScriptFieldType(String name, LongFieldScript.Factory scriptFactory, LongFieldScript.Factory scriptFactory, Script script, Map meta, - CheckedBiConsumer toXContent + ToXContent toXContent ) { super(name, scriptFactory::newFactory, script, meta, toXContent); } diff --git a/server/src/test/java/org/elasticsearch/index/IndexSortSettingsTests.java b/server/src/test/java/org/elasticsearch/index/IndexSortSettingsTests.java index 54504d13c5163..638439a1d57f3 100644 --- a/server/src/test/java/org/elasticsearch/index/IndexSortSettingsTests.java +++ b/server/src/test/java/org/elasticsearch/index/IndexSortSettingsTests.java @@ -10,11 +10,11 @@ import org.apache.lucene.search.Query; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.time.DateMathParser; import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.mapper.MappedFieldType; -import org.elasticsearch.index.mapper.RuntimeFieldType; +import org.elasticsearch.index.mapper.TextSearchInfo; +import org.elasticsearch.index.mapper.ValueFetcher; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.indices.breaker.NoneCircuitBreakerService; import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache; @@ -23,7 +23,6 @@ import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.test.ESTestCase; -import java.time.ZoneId; import java.util.Collections; import java.util.function.Supplier; @@ -141,13 +140,7 @@ public void testIndexSorting() { IndicesFieldDataCache cache = new IndicesFieldDataCache(Settings.EMPTY, null); NoneCircuitBreakerService circuitBreakerService = new NoneCircuitBreakerService(); final IndexFieldDataService indexFieldDataService = new IndexFieldDataService(indexSettings, cache, circuitBreakerService, null); - MappedFieldType fieldType = new RuntimeFieldType("field", Collections.emptyMap(), null) { - @Override - protected Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, ZoneId timeZone, - DateMathParser parser, SearchExecutionContext context) { - throw new UnsupportedOperationException(); - } - + MappedFieldType fieldType = new MappedFieldType("field", false, false, false, TextSearchInfo.NONE, Collections.emptyMap()) { @Override public String typeName() { return null; @@ -159,6 +152,11 @@ public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, S return null; } + @Override + public ValueFetcher valueFetcher(SearchExecutionContext context, String format) { + throw new UnsupportedOperationException(); + } + @Override public Query termQuery(Object value, SearchExecutionContext context) { throw new UnsupportedOperationException(); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/FieldAliasMapperValidationTests.java b/server/src/test/java/org/elasticsearch/index/mapper/FieldAliasMapperValidationTests.java index 747abb8fbe6f1..83cf02320999b 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/FieldAliasMapperValidationTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/FieldAliasMapperValidationTests.java @@ -199,7 +199,7 @@ private static MappingLookup createMappingLookup(List fieldMappers, List fieldAliasMappers, List runtimeFields) { RootObjectMapper.Builder builder = new RootObjectMapper.Builder("_doc", Version.CURRENT); - Map runtimeFieldTypes = runtimeFields.stream().collect(Collectors.toMap(MappedFieldType::name, r -> r)); + Map runtimeFieldTypes = runtimeFields.stream().collect(Collectors.toMap(RuntimeFieldType::name, r -> r)); builder.setRuntime(runtimeFieldTypes); Mapping mapping = new Mapping(builder.build(new ContentPath()), new MetadataFieldMapper[0], Collections.emptyMap()); return new MappingLookup(mapping, fieldMappers, objectMappers, fieldAliasMappers, null, null, null); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/MappingLookupTests.java b/server/src/test/java/org/elasticsearch/index/mapper/MappingLookupTests.java index 59d5c4e2994bb..3b0569c63c78e 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/MappingLookupTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/MappingLookupTests.java @@ -36,7 +36,7 @@ private static MappingLookup createMappingLookup(List fieldMappers, List objectMappers, List runtimeFields) { RootObjectMapper.Builder builder = new RootObjectMapper.Builder("_doc", Version.CURRENT); - Map runtimeFieldTypes = runtimeFields.stream().collect(Collectors.toMap(MappedFieldType::name, r -> r)); + Map runtimeFieldTypes = runtimeFields.stream().collect(Collectors.toMap(RuntimeFieldType::name, r -> r)); builder.setRuntime(runtimeFieldTypes); Mapping mapping = new Mapping(builder.build(new ContentPath()), new MetadataFieldMapper[0], Collections.emptyMap()); return new MappingLookup(mapping, fieldMappers, objectMappers, emptyList(), null, null, null); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldMapperTests.java index 0fda397e3e621..fde4cb56adc78 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/RangeFieldMapperTests.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.net.InetAddress; +import java.util.Collections; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -327,7 +328,8 @@ public void testSerializeDefaults() throws Exception { DocumentMapper docMapper = createDocumentMapper(fieldMapping(b -> b.field("type", type))); RangeFieldMapper mapper = (RangeFieldMapper) docMapper.mapping().getRoot().getMapper("field"); XContentBuilder builder = XContentFactory.jsonBuilder().startObject(); - mapper.doXContentBody(builder, true, ToXContent.EMPTY_PARAMS); + ToXContent.MapParams params = new ToXContent.MapParams(Collections.singletonMap("include_defaults", "true")); + mapper.doXContentBody(builder, params); String got = Strings.toString(builder.endObject()); // if type is date_range we check that the mapper contains the default format and locale diff --git a/server/src/test/java/org/elasticsearch/index/mapper/TestRuntimeField.java b/server/src/test/java/org/elasticsearch/index/mapper/TestRuntimeField.java index fd359fe1bde14..5e2d90250f1f7 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/TestRuntimeField.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/TestRuntimeField.java @@ -9,18 +9,18 @@ package org.elasticsearch.index.mapper; import org.apache.lucene.search.Query; -import org.elasticsearch.common.time.DateMathParser; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.SearchExecutionContext; -import java.time.ZoneId; +import java.io.IOException; import java.util.Collections; -public class TestRuntimeField extends RuntimeFieldType { +public class TestRuntimeField extends MappedFieldType implements RuntimeFieldType { private final String type; public TestRuntimeField(String name, String type) { - super(name, Collections.emptyMap(), null); + super(name, false, false, false, TextSearchInfo.NONE, Collections.emptyMap()); this.type = type; } @@ -29,14 +29,23 @@ public String typeName() { return type; } + @Override + public MappedFieldType asMappedFieldType() { + return this; + } + + @Override + public ValueFetcher valueFetcher(SearchExecutionContext context, String format) { + throw new UnsupportedOperationException(); + } + @Override public Query termQuery(Object value, SearchExecutionContext context) { return null; } @Override - protected Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, - ZoneId timeZone, DateMathParser parser, SearchExecutionContext context) { - throw new UnsupportedOperationException(); + public void doXContentBody(XContentBuilder builder, Params params) throws IOException { + } } diff --git a/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java b/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java index f3297212a1335..0a1f1cbdbc136 100644 --- a/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java @@ -324,7 +324,7 @@ public void testFielddataLookupOneFieldManyReferences() throws IOException { private static MappingLookup createMappingLookup(List concreteFields, List runtimeFields) { List mappers = concreteFields.stream().map(MockFieldMapper::new).collect(Collectors.toList()); RootObjectMapper.Builder builder = new RootObjectMapper.Builder("_doc", Version.CURRENT); - Map runtimeFieldTypes = runtimeFields.stream().collect(Collectors.toMap(MappedFieldType::name, r -> r)); + Map runtimeFieldTypes = runtimeFields.stream().collect(Collectors.toMap(RuntimeFieldType::name, r -> r)); builder.setRuntime(runtimeFieldTypes); Mapping mapping = new Mapping(builder.build(new ContentPath()), new MetadataFieldMapper[0], Collections.emptyMap()); return new MappingLookup(mapping, mappers, Collections.emptyList(), Collections.emptyList(), null, null, null); diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldTypeTests.java index 8d01176b4aba4..1e510ebee0db6 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/BooleanScriptFieldTypeTests.java @@ -429,6 +429,6 @@ public void execute() { } private static BooleanScriptFieldType build(Script script) { - return new BooleanScriptFieldType("test", factory(script), script, emptyMap(), (b, d) -> {}); + return new BooleanScriptFieldType("test", factory(script), script, emptyMap(), (builder, params) -> builder); } } diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldTypeTests.java index dbe2f9b12d3fb..7363346ef8136 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/DateScriptFieldTypeTests.java @@ -501,7 +501,7 @@ public void execute() { } private static DateScriptFieldType build(Script script, DateFormatter dateTimeFormatter) { - return new DateScriptFieldType("test", factory(script), dateTimeFormatter, script, emptyMap(), (b, d) -> {}); + return new DateScriptFieldType("test", factory(script), dateTimeFormatter, script, emptyMap(), (builder, params) -> builder); } private static long randomDate() { diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldTypeTests.java index 5a590facece45..f62ac71e2d469 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/DoubleScriptFieldTypeTests.java @@ -271,6 +271,6 @@ public void execute() { } private static DoubleScriptFieldType build(Script script) { - return new DoubleScriptFieldType("test", factory(script), script, emptyMap(), (b, d) -> {}); + return new DoubleScriptFieldType("test", factory(script), script, emptyMap(), (builder, params) -> builder); } } diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldTypeTests.java index 7be89381a6805..5b3e147ba96bc 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/GeoPointScriptFieldTypeTests.java @@ -231,6 +231,6 @@ public void execute() { } private static GeoPointScriptFieldType build(Script script) { - return new GeoPointScriptFieldType("test", factory(script), script, emptyMap(), (b, d) -> {}); + return new GeoPointScriptFieldType("test", factory(script), script, emptyMap(), (builder, params) -> builder); } } diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldTypeTests.java index a1945bf1c4eed..95b3305da3385 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/IpScriptFieldTypeTests.java @@ -288,6 +288,6 @@ public void execute() { } private static IpScriptFieldType build(Script script) { - return new IpScriptFieldType("test", factory(script), script, emptyMap(), (b, d) -> {}); + return new IpScriptFieldType("test", factory(script), script, emptyMap(), (builder, params) -> builder); } } diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldTypeTests.java index c54deed2ec3a2..a6ea22b0577dc 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/KeywordScriptFieldTypeTests.java @@ -403,6 +403,6 @@ public void execute() { } private static KeywordScriptFieldType build(Script script) { - return new KeywordScriptFieldType("test", factory(script), script, emptyMap(), (b, d) -> {}); + return new KeywordScriptFieldType("test", factory(script), script, emptyMap(), (builder, params) -> builder); } } diff --git a/server/src/test/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldTypeTests.java b/server/src/test/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldTypeTests.java index 86716d4261449..b8a3d0b335978 100644 --- a/server/src/test/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/runtimefields/mapper/LongScriptFieldTypeTests.java @@ -316,6 +316,6 @@ public void execute() { } private static LongScriptFieldType build(Script script) { - return new LongScriptFieldType("test", factory(script), script, emptyMap(), (b, d) -> {}); + return new LongScriptFieldType("test", factory(script), script, emptyMap(), (builder, params) -> builder); } }