Skip to content

Separate AbstractScriptFieldType from RuntimeField implementations #74768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,40 @@
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.query.SearchExecutionContext;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
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<LeafFactory> extends MappedFieldType implements RuntimeField {
abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {

protected final Script script;
private final Function<SearchLookup, LeafFactory> factory;
private final ToXContent toXContent;

AbstractScriptFieldType(
String name,
Function<SearchLookup, LeafFactory> factory,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, false, false, false, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.factory = factory;
this.script = script;
this.toXContent = toXContent;
}

@Override
public final Collection<MappedFieldType> asMappedFieldTypes() {
return Collections.singleton(this);
}

@Override
public final void doXContentBody(XContentBuilder builder, Params params) throws IOException {
toXContent.toXContent(builder, params);
this.script = Objects.requireNonNull(script);
}

@Override
Expand Down Expand Up @@ -205,7 +190,7 @@ protected final LeafFactory leafFactory(SearchExecutionContext context) {

// Placeholder Script for source-only fields
// TODO rework things so that we don't need this
private static final Script DEFAULT_SCRIPT = new Script("");
protected static final Script DEFAULT_SCRIPT = new Script("");

abstract static class Builder<Factory> extends RuntimeField.Builder {
private final ScriptContext<Factory> scriptContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,42 @@ public final class BooleanScriptFieldType extends AbstractScriptFieldType<Boolea
new Builder<>(name, BooleanFieldScript.CONTEXT, BooleanFieldScript.PARSE_FROM_SOURCE) {
@Override
RuntimeField newRuntimeField(BooleanFieldScript.Factory scriptFactory) {
return new BooleanScriptFieldType(name, scriptFactory, getScript(), meta(), this);
return runtimeField(name, this, scriptFactory, getScript(), meta());
}
});

public BooleanScriptFieldType(String name) {
this(name, BooleanFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder);
private static RuntimeField runtimeField(
String name,
ToXContent toXContent,
BooleanFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta
) {
return new LeafRuntimeField(name, new BooleanScriptFieldType(name, scriptFactory, script, meta), toXContent) {
@Override
public String typeName() {
return BooleanFieldMapper.CONTENT_TYPE;
}
};
}

public static RuntimeField sourceOnly(String name) {
return runtimeField(
name,
(builder, params) -> builder,
BooleanFieldScript.PARSE_FROM_SOURCE,
DEFAULT_SCRIPT,
Collections.emptyMap()
);
}

BooleanScriptFieldType(
String name,
BooleanFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,32 +82,53 @@ RuntimeField newRuntimeField(DateFieldScript.Factory scriptFactory) {
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);
return new DateScriptFieldType(name, scriptFactory, dateTimeFormatter, getScript(), meta(), this);
return runtimeField(name, this, dateTimeFormatter, scriptFactory, getScript(), meta());
}
});

private final DateFormatter dateTimeFormatter;
private final DateMathParser dateMathParser;

public DateScriptFieldType(String name, DateFormatter dateTimeFormatter) {
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());
private static RuntimeField runtimeField(
String name,
ToXContent toXContent,
DateFormatter dateFormatter,
DateFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta
) {
return new LeafRuntimeField(name, new DateScriptFieldType(name, scriptFactory, dateFormatter, script, meta), toXContent) {
@Override
public String typeName() {
return DateFieldMapper.CONTENT_TYPE;
}
return builder;
});
};
}

public static RuntimeField sourceOnly(String name, DateFormatter dateTimeFormatter) {
return runtimeField(
name,
(builder, params) -> {
if (DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern().equals(dateTimeFormatter.pattern()) == false) {
builder.field("format", dateTimeFormatter.pattern());
}
return builder;
},
dateTimeFormatter,
DateFieldScript.PARSE_FROM_SOURCE,
DEFAULT_SCRIPT,
Collections.emptyMap());
}

DateScriptFieldType(
String name,
DateFieldScript.Factory scriptFactory,
DateFormatter dateTimeFormatter,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, dateTimeFormatter),
script, meta, toXContent);
script, meta);
this.dateTimeFormatter = dateTimeFormatter;
this.dateMathParser = dateTimeFormatter.toDateMathParser();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,41 @@ public final class DoubleScriptFieldType extends AbstractScriptFieldType<DoubleF
new Builder<>(name, DoubleFieldScript.CONTEXT, DoubleFieldScript.PARSE_FROM_SOURCE) {
@Override
RuntimeField newRuntimeField(DoubleFieldScript.Factory scriptFactory) {
return new DoubleScriptFieldType(name, scriptFactory, getScript(), meta(), this);
return runtimeField(name, this, scriptFactory, getScript(), meta());
}
});

public DoubleScriptFieldType(String name) {
this(name, DoubleFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder);
private static RuntimeField runtimeField(
String name,
ToXContent toXContent,
DoubleFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta
) {
return new LeafRuntimeField(name, new DoubleScriptFieldType(name, scriptFactory, script, meta), toXContent) {
@Override
public String typeName() {
return NumberType.DOUBLE.typeName();
}
};
}

public static RuntimeField sourceOnly(String name) {
return runtimeField(
name,
(builder, params) -> builder,
DoubleFieldScript.PARSE_FROM_SOURCE,
DEFAULT_SCRIPT,
Collections.emptyMap());
}

DoubleScriptFieldType(
String name,
DoubleFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,31 +320,31 @@ static void createDynamicField(RuntimeField runtimeField, ParseContext context)
@Override
public void newDynamicStringField(ParseContext context, String name) {
String fullName = context.path().pathAsText(name);
createDynamicField(new KeywordScriptFieldType(fullName), context);
createDynamicField(KeywordScriptFieldType.sourceOnly(fullName), context);
}

@Override
public void newDynamicLongField(ParseContext context, String name) {
String fullName = context.path().pathAsText(name);
createDynamicField(new LongScriptFieldType(fullName), context);
createDynamicField(LongScriptFieldType.sourceOnly(fullName), context);
}

@Override
public void newDynamicDoubleField(ParseContext context, String name) {
String fullName = context.path().pathAsText(name);
createDynamicField(new DoubleScriptFieldType(fullName), context);
createDynamicField(DoubleScriptFieldType.sourceOnly(fullName), context);
}

@Override
public void newDynamicBooleanField(ParseContext context, String name) {
String fullName = context.path().pathAsText(name);
createDynamicField(new BooleanScriptFieldType(fullName), context);
createDynamicField(BooleanScriptFieldType.sourceOnly(fullName), context);
}

@Override
public void newDynamicDateField(ParseContext context, String name, DateFormatter dateFormatter) {
String fullName = context.path().pathAsText(name);
createDynamicField(new DateScriptFieldType(fullName, dateFormatter), context);
createDynamicField(DateScriptFieldType.sourceOnly(fullName, dateFormatter), context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.time.DateMathParser;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.geometry.Geometry;
import org.elasticsearch.index.fielddata.GeoPointScriptFieldData;
import org.elasticsearch.index.query.SearchExecutionContext;
Expand All @@ -40,18 +39,22 @@ public final class GeoPointScriptFieldType extends AbstractScriptFieldType<GeoPo
new Builder<>(name, GeoPointFieldScript.CONTEXT, GeoPointFieldScript.PARSE_FROM_SOURCE) {
@Override
RuntimeField newRuntimeField(GeoPointFieldScript.Factory scriptFactory) {
return new GeoPointScriptFieldType(name, scriptFactory, getScript(), meta(), this);
return new LeafRuntimeField(name, new GeoPointScriptFieldType(name, scriptFactory, getScript(), meta()), this) {
@Override
public String typeName() {
return GeoPointFieldMapper.CONTENT_TYPE;
}
};
}
});

GeoPointScriptFieldType(
String name,
GeoPointFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.core.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.ToXContent;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.index.fielddata.IpScriptFieldData;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.script.IpFieldScript;
Expand All @@ -46,18 +45,22 @@ public final class IpScriptFieldType extends AbstractScriptFieldType<IpFieldScri
new Builder<>(name, IpFieldScript.CONTEXT, IpFieldScript.PARSE_FROM_SOURCE) {
@Override
RuntimeField newRuntimeField(IpFieldScript.Factory scriptFactory) {
return new IpScriptFieldType(name, scriptFactory, getScript(), meta(), this);
return new LeafRuntimeField(name, new IpScriptFieldType(name, scriptFactory, getScript(), meta()), this) {
@Override
public String typeName() {
return IpFieldMapper.CONTENT_TYPE;
}
};
}
});

IpScriptFieldType(
String name,
IpFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,41 @@ public final class KeywordScriptFieldType extends AbstractScriptFieldType<String
new Builder<>(name, StringFieldScript.CONTEXT, StringFieldScript.PARSE_FROM_SOURCE) {
@Override
RuntimeField newRuntimeField(StringFieldScript.Factory scriptFactory) {
return new KeywordScriptFieldType(name, scriptFactory, getScript(), meta(), this);
return runtimeField(name, this, scriptFactory, getScript(), meta());
}
});

public KeywordScriptFieldType(String name) {
this(name, StringFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder);
private static RuntimeField runtimeField(
String name,
ToXContent toXContent,
StringFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta
) {
return new LeafRuntimeField(name, new KeywordScriptFieldType(name, scriptFactory, script, meta), toXContent) {
@Override
public String typeName() {
return KeywordFieldMapper.CONTENT_TYPE;
}
};
}

public static RuntimeField sourceOnly(String name) {
return runtimeField(
name,
(builder, params) -> builder,
StringFieldScript.PARSE_FROM_SOURCE,
DEFAULT_SCRIPT,
Collections.emptyMap());
}

public KeywordScriptFieldType(
String name,
StringFieldScript.Factory scriptFactory,
Script script,
Map<String, String> meta,
ToXContent toXContent
Map<String, String> meta
) {
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
}

@Override
Expand Down
Loading