Skip to content

Commit 8dab892

Browse files
committed
Separate AbstractScriptFieldType from RuntimeField implementations (#74768)
AbstractScriptFieldType extends MappedFieldType and also implements RuntimeField. This means that the name() of a runtime field has to be the same as the name() of its corresponding mapped field type. However, for object fields we will want the nested child fields to have a specific short name, while their MappedFieldType will need to have a name that includes the parent. To make this distinction possible, this commit changes AbstractScriptFieldType subclasses to return their own implementations of RuntimeField from their type parsers instead of implementing the interface directly.
1 parent 346d2ca commit 8dab892

19 files changed

+218
-83
lines changed

server/src/main/java/org/elasticsearch/index/mapper/AbstractScriptFieldType.java

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,55 +17,40 @@
1717
import org.elasticsearch.common.geo.ShapeRelation;
1818
import org.elasticsearch.common.time.DateMathParser;
1919
import org.elasticsearch.common.unit.Fuzziness;
20-
import org.elasticsearch.common.xcontent.ToXContent;
21-
import org.elasticsearch.common.xcontent.XContentBuilder;
2220
import org.elasticsearch.index.query.SearchExecutionContext;
2321
import org.elasticsearch.script.Script;
2422
import org.elasticsearch.script.ScriptContext;
2523
import org.elasticsearch.script.ScriptType;
2624
import org.elasticsearch.search.lookup.SearchLookup;
2725

28-
import java.io.IOException;
2926
import java.time.ZoneId;
3027
import java.util.ArrayList;
31-
import java.util.Collection;
3228
import java.util.Collections;
3329
import java.util.List;
3430
import java.util.Locale;
3531
import java.util.Map;
32+
import java.util.Objects;
3633
import java.util.function.Function;
3734

3835
import static org.elasticsearch.search.SearchService.ALLOW_EXPENSIVE_QUERIES;
3936

4037
/**
4138
* Abstract base {@linkplain MappedFieldType} for runtime fields based on a script.
4239
*/
43-
abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType implements RuntimeField {
40+
abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
41+
4442
protected final Script script;
4543
private final Function<SearchLookup, LeafFactory> factory;
46-
private final ToXContent toXContent;
4744

4845
AbstractScriptFieldType(
4946
String name,
5047
Function<SearchLookup, LeafFactory> factory,
5148
Script script,
52-
Map<String, String> meta,
53-
ToXContent toXContent
49+
Map<String, String> meta
5450
) {
5551
super(name, false, false, false, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
5652
this.factory = factory;
57-
this.script = script;
58-
this.toXContent = toXContent;
59-
}
60-
61-
@Override
62-
public final Collection<MappedFieldType> asMappedFieldTypes() {
63-
return Collections.singleton(this);
64-
}
65-
66-
@Override
67-
public final void doXContentBody(XContentBuilder builder, Params params) throws IOException {
68-
toXContent.toXContent(builder, params);
53+
this.script = Objects.requireNonNull(script);
6954
}
7055

7156
@Override
@@ -205,7 +190,7 @@ protected final LeafFactory leafFactory(SearchExecutionContext context) {
205190

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

210195
abstract static class Builder<Factory> extends RuntimeField.Builder {
211196
private final ScriptContext<Factory> scriptContext;

server/src/main/java/org/elasticsearch/index/mapper/BooleanScriptFieldType.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,42 @@ public final class BooleanScriptFieldType extends AbstractScriptFieldType<Boolea
3737
new Builder<BooleanFieldScript.Factory>(name, BooleanFieldScript.CONTEXT, BooleanFieldScript.PARSE_FROM_SOURCE) {
3838
@Override
3939
RuntimeField newRuntimeField(BooleanFieldScript.Factory scriptFactory) {
40-
return new BooleanScriptFieldType(name, scriptFactory, getScript(), meta(), this);
40+
return runtimeField(name, this, scriptFactory, getScript(), meta());
4141
}
4242
});
4343

44-
public BooleanScriptFieldType(String name) {
45-
this(name, BooleanFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder);
44+
private static RuntimeField runtimeField(
45+
String name,
46+
ToXContent toXContent,
47+
BooleanFieldScript.Factory scriptFactory,
48+
Script script,
49+
Map<String, String> meta
50+
) {
51+
return new LeafRuntimeField(name, new BooleanScriptFieldType(name, scriptFactory, script, meta), toXContent) {
52+
@Override
53+
public String typeName() {
54+
return BooleanFieldMapper.CONTENT_TYPE;
55+
}
56+
};
57+
}
58+
59+
public static RuntimeField sourceOnly(String name) {
60+
return runtimeField(
61+
name,
62+
(builder, params) -> builder,
63+
BooleanFieldScript.PARSE_FROM_SOURCE,
64+
DEFAULT_SCRIPT,
65+
Collections.emptyMap()
66+
);
4667
}
4768

4869
BooleanScriptFieldType(
4970
String name,
5071
BooleanFieldScript.Factory scriptFactory,
5172
Script script,
52-
Map<String, String> meta,
53-
ToXContent toXContent
73+
Map<String, String> meta
5474
) {
55-
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
75+
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
5676
}
5777

5878
@Override

server/src/main/java/org/elasticsearch/index/mapper/DateScriptFieldType.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,31 +82,52 @@ RuntimeField newRuntimeField(DateFieldScript.Factory scriptFactory) {
8282
String pattern = format.getValue() == null ? DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern() : format.getValue();
8383
Locale locale = this.locale.getValue() == null ? Locale.ROOT : this.locale.getValue();
8484
DateFormatter dateTimeFormatter = DateFormatter.forPattern(pattern).withLocale(locale);
85-
return new DateScriptFieldType(name, scriptFactory, dateTimeFormatter, getScript(), meta(), this);
85+
return runtimeField(name, this, dateTimeFormatter, scriptFactory, getScript(), meta());
8686
}
8787
});
8888

8989
private final DateFormatter dateTimeFormatter;
9090

91-
public DateScriptFieldType(String name, DateFormatter dateTimeFormatter) {
92-
this(name, DateFieldScript.PARSE_FROM_SOURCE, dateTimeFormatter, null, Collections.emptyMap(), (builder, params) -> {
93-
if (DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern().equals(dateTimeFormatter.pattern()) == false) {
94-
builder.field("format", dateTimeFormatter.pattern());
91+
private static RuntimeField runtimeField(
92+
String name,
93+
ToXContent toXContent,
94+
DateFormatter dateFormatter,
95+
DateFieldScript.Factory scriptFactory,
96+
Script script,
97+
Map<String, String> meta
98+
) {
99+
return new LeafRuntimeField(name, new DateScriptFieldType(name, scriptFactory, dateFormatter, script, meta), toXContent) {
100+
@Override
101+
public String typeName() {
102+
return DateFieldMapper.CONTENT_TYPE;
95103
}
96-
return builder;
97-
});
104+
};
105+
}
106+
107+
public static RuntimeField sourceOnly(String name, DateFormatter dateTimeFormatter) {
108+
return runtimeField(
109+
name,
110+
(builder, params) -> {
111+
if (DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern().equals(dateTimeFormatter.pattern()) == false) {
112+
builder.field("format", dateTimeFormatter.pattern());
113+
}
114+
return builder;
115+
},
116+
dateTimeFormatter,
117+
DateFieldScript.PARSE_FROM_SOURCE,
118+
DEFAULT_SCRIPT,
119+
Collections.emptyMap());
98120
}
99121

100122
DateScriptFieldType(
101123
String name,
102124
DateFieldScript.Factory scriptFactory,
103125
DateFormatter dateTimeFormatter,
104126
Script script,
105-
Map<String, String> meta,
106-
ToXContent toXContent
127+
Map<String, String> meta
107128
) {
108129
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, dateTimeFormatter),
109-
script, meta, toXContent);
130+
script, meta);
110131
this.dateTimeFormatter = dateTimeFormatter;
111132
}
112133

server/src/main/java/org/elasticsearch/index/mapper/DoubleScriptFieldType.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,41 @@ public final class DoubleScriptFieldType extends AbstractScriptFieldType<DoubleF
3838
new Builder<DoubleFieldScript.Factory>(name, DoubleFieldScript.CONTEXT, DoubleFieldScript.PARSE_FROM_SOURCE) {
3939
@Override
4040
RuntimeField newRuntimeField(DoubleFieldScript.Factory scriptFactory) {
41-
return new DoubleScriptFieldType(name, scriptFactory, getScript(), meta(), this);
41+
return runtimeField(name, this, scriptFactory, getScript(), meta());
4242
}
4343
});
4444

45-
public DoubleScriptFieldType(String name) {
46-
this(name, DoubleFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder);
45+
private static RuntimeField runtimeField(
46+
String name,
47+
ToXContent toXContent,
48+
DoubleFieldScript.Factory scriptFactory,
49+
Script script,
50+
Map<String, String> meta
51+
) {
52+
return new LeafRuntimeField(name, new DoubleScriptFieldType(name, scriptFactory, script, meta), toXContent) {
53+
@Override
54+
public String typeName() {
55+
return NumberType.DOUBLE.typeName();
56+
}
57+
};
58+
}
59+
60+
public static RuntimeField sourceOnly(String name) {
61+
return runtimeField(
62+
name,
63+
(builder, params) -> builder,
64+
DoubleFieldScript.PARSE_FROM_SOURCE,
65+
DEFAULT_SCRIPT,
66+
Collections.emptyMap());
4767
}
4868

4969
DoubleScriptFieldType(
5070
String name,
5171
DoubleFieldScript.Factory scriptFactory,
5272
Script script,
53-
Map<String, String> meta,
54-
ToXContent toXContent
73+
Map<String, String> meta
5574
) {
56-
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
75+
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
5776
}
5877

5978
@Override

server/src/main/java/org/elasticsearch/index/mapper/DynamicFieldsBuilder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,31 +320,31 @@ static void createDynamicField(RuntimeField runtimeField, ParseContext context)
320320
@Override
321321
public void newDynamicStringField(ParseContext context, String name) {
322322
String fullName = context.path().pathAsText(name);
323-
createDynamicField(new KeywordScriptFieldType(fullName), context);
323+
createDynamicField(KeywordScriptFieldType.sourceOnly(fullName), context);
324324
}
325325

326326
@Override
327327
public void newDynamicLongField(ParseContext context, String name) {
328328
String fullName = context.path().pathAsText(name);
329-
createDynamicField(new LongScriptFieldType(fullName), context);
329+
createDynamicField(LongScriptFieldType.sourceOnly(fullName), context);
330330
}
331331

332332
@Override
333333
public void newDynamicDoubleField(ParseContext context, String name) {
334334
String fullName = context.path().pathAsText(name);
335-
createDynamicField(new DoubleScriptFieldType(fullName), context);
335+
createDynamicField(DoubleScriptFieldType.sourceOnly(fullName), context);
336336
}
337337

338338
@Override
339339
public void newDynamicBooleanField(ParseContext context, String name) {
340340
String fullName = context.path().pathAsText(name);
341-
createDynamicField(new BooleanScriptFieldType(fullName), context);
341+
createDynamicField(BooleanScriptFieldType.sourceOnly(fullName), context);
342342
}
343343

344344
@Override
345345
public void newDynamicDateField(ParseContext context, String name, DateFormatter dateFormatter) {
346346
String fullName = context.path().pathAsText(name);
347-
createDynamicField(new DateScriptFieldType(fullName, dateFormatter), context);
347+
createDynamicField(DateScriptFieldType.sourceOnly(fullName, dateFormatter), context);
348348
}
349349
}
350350
}

server/src/main/java/org/elasticsearch/index/mapper/GeoPointScriptFieldType.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import org.elasticsearch.common.geo.ShapeRelation;
1919
import org.elasticsearch.common.time.DateMathParser;
2020
import org.elasticsearch.common.unit.DistanceUnit;
21-
import org.elasticsearch.common.xcontent.ToXContent;
2221
import org.elasticsearch.geometry.Geometry;
2322
import org.elasticsearch.index.fielddata.GeoPointScriptFieldData;
2423
import org.elasticsearch.index.query.SearchExecutionContext;
@@ -40,18 +39,22 @@ public final class GeoPointScriptFieldType extends AbstractScriptFieldType<GeoPo
4039
new Builder<GeoPointFieldScript.Factory>(name, GeoPointFieldScript.CONTEXT, GeoPointFieldScript.PARSE_FROM_SOURCE) {
4140
@Override
4241
RuntimeField newRuntimeField(GeoPointFieldScript.Factory scriptFactory) {
43-
return new GeoPointScriptFieldType(name, scriptFactory, getScript(), meta(), this);
42+
return new LeafRuntimeField(name, new GeoPointScriptFieldType(name, scriptFactory, getScript(), meta()), this) {
43+
@Override
44+
public String typeName() {
45+
return GeoPointFieldMapper.CONTENT_TYPE;
46+
}
47+
};
4448
}
4549
});
4650

4751
GeoPointScriptFieldType(
4852
String name,
4953
GeoPointFieldScript.Factory scriptFactory,
5054
Script script,
51-
Map<String, String> meta,
52-
ToXContent toXContent
55+
Map<String, String> meta
5356
) {
54-
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
57+
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
5558
}
5659

5760
@Override

server/src/main/java/org/elasticsearch/index/mapper/IpScriptFieldType.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@
1313
import org.apache.lucene.search.BooleanQuery;
1414
import org.apache.lucene.search.Query;
1515
import org.apache.lucene.util.BytesRef;
16-
import org.elasticsearch.core.Tuple;
1716
import org.elasticsearch.common.lucene.BytesRefs;
1817
import org.elasticsearch.common.network.InetAddresses;
1918
import org.elasticsearch.common.time.DateMathParser;
2019
import org.elasticsearch.common.util.BigArrays;
2120
import org.elasticsearch.common.util.BytesRefHash;
22-
import org.elasticsearch.common.xcontent.ToXContent;
21+
import org.elasticsearch.core.Tuple;
2322
import org.elasticsearch.index.fielddata.IpScriptFieldData;
2423
import org.elasticsearch.index.query.SearchExecutionContext;
2524
import org.elasticsearch.script.IpFieldScript;
@@ -46,18 +45,22 @@ public final class IpScriptFieldType extends AbstractScriptFieldType<IpFieldScri
4645
new Builder<IpFieldScript.Factory>(name, IpFieldScript.CONTEXT, IpFieldScript.PARSE_FROM_SOURCE) {
4746
@Override
4847
RuntimeField newRuntimeField(IpFieldScript.Factory scriptFactory) {
49-
return new IpScriptFieldType(name, scriptFactory, getScript(), meta(), this);
48+
return new LeafRuntimeField(name, new IpScriptFieldType(name, scriptFactory, getScript(), meta()), this) {
49+
@Override
50+
public String typeName() {
51+
return IpFieldMapper.CONTENT_TYPE;
52+
}
53+
};
5054
}
5155
});
5256

5357
IpScriptFieldType(
5458
String name,
5559
IpFieldScript.Factory scriptFactory,
5660
Script script,
57-
Map<String, String> meta,
58-
ToXContent toXContent
61+
Map<String, String> meta
5962
) {
60-
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
63+
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
6164
}
6265

6366
@Override

server/src/main/java/org/elasticsearch/index/mapper/KeywordScriptFieldType.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,41 @@ public final class KeywordScriptFieldType extends AbstractScriptFieldType<String
4545
new Builder<StringFieldScript.Factory>(name, StringFieldScript.CONTEXT, StringFieldScript.PARSE_FROM_SOURCE) {
4646
@Override
4747
RuntimeField newRuntimeField(StringFieldScript.Factory scriptFactory) {
48-
return new KeywordScriptFieldType(name, scriptFactory, getScript(), meta(), this);
48+
return runtimeField(name, this, scriptFactory, getScript(), meta());
4949
}
5050
});
5151

52-
public KeywordScriptFieldType(String name) {
53-
this(name, StringFieldScript.PARSE_FROM_SOURCE, null, Collections.emptyMap(), (builder, params) -> builder);
52+
private static RuntimeField runtimeField(
53+
String name,
54+
ToXContent toXContent,
55+
StringFieldScript.Factory scriptFactory,
56+
Script script,
57+
Map<String, String> meta
58+
) {
59+
return new LeafRuntimeField(name, new KeywordScriptFieldType(name, scriptFactory, script, meta), toXContent) {
60+
@Override
61+
public String typeName() {
62+
return KeywordFieldMapper.CONTENT_TYPE;
63+
}
64+
};
65+
}
66+
67+
public static RuntimeField sourceOnly(String name) {
68+
return runtimeField(
69+
name,
70+
(builder, params) -> builder,
71+
StringFieldScript.PARSE_FROM_SOURCE,
72+
DEFAULT_SCRIPT,
73+
Collections.emptyMap());
5474
}
5575

5676
public KeywordScriptFieldType(
5777
String name,
5878
StringFieldScript.Factory scriptFactory,
5979
Script script,
60-
Map<String, String> meta,
61-
ToXContent toXContent
80+
Map<String, String> meta
6281
) {
63-
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta, toXContent);
82+
super(name, searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup), script, meta);
6483
}
6584

6685
@Override

0 commit comments

Comments
 (0)