Skip to content
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

Emit multiple fields from the same runtime field script #73252

Closed
wants to merge 12 commits into from
Prev Previous commit
Next Next commit
Merge branch 'master' into poc/emit_multiple_fields
javanna committed Jul 7, 2021
commit 15bd02f06cb6e4bd636d4501625682887466d199
Original file line number Diff line number Diff line change
@@ -213,16 +213,14 @@ abstract static class Builder<Factory> extends RuntimeField.Builder {

abstract Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory);

abstract RuntimeField newRuntimeField(Factory scriptFactory);

@Override
protected final RuntimeField createRuntimeField(MappingParserContext parserContext,
Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
if (script.get() == null) {
if (parentScriptFactory == null) {
return newRuntimeField(getParseFromSourceFactory());
return createRuntimeField(getParseFromSourceFactory());
}
return newRuntimeField(getObjectSubfieldFactory(parentScriptFactory));
return createRuntimeField(getObjectSubfieldFactory(parentScriptFactory));
}
Factory factory = parserContext.scriptCompiler().compile(script.getValue(), scriptContext);
return createRuntimeField(factory);
Original file line number Diff line number Diff line change
@@ -33,27 +33,11 @@

public final class BooleanScriptFieldType extends AbstractScriptFieldType<BooleanFieldScript.LeafFactory> {

public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(name ->
new Builder<>(name, BooleanFieldScript.CONTEXT) {
@Override
RuntimeField newRuntimeField(BooleanFieldScript.Factory scriptFactory) {
return runtimeField(name, this, scriptFactory, getScript(), meta());
}

@Override
BooleanFieldScript.Factory getParseFromSourceFactory() {
return BooleanFieldScript.PARSE_FROM_SOURCE;
}

@Override
BooleanFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return BooleanFieldScript.objectAdapter(parentScriptFactory);
}
});
public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(Builder::new);

private static class Builder extends AbstractScriptFieldType.Builder<BooleanFieldScript.Factory> {
Builder(String name) {
super(name, BooleanFieldScript.CONTEXT, BooleanFieldScript.PARSE_FROM_SOURCE);
super(name, BooleanFieldScript.CONTEXT);
}

@Override
@@ -63,6 +47,17 @@ AbstractScriptFieldType<?> createFieldType(String name,
Map<String, String> meta) {
return new BooleanScriptFieldType(name, factory, script, meta);
}

@Override
BooleanFieldScript.Factory getParseFromSourceFactory() {
return BooleanFieldScript.PARSE_FROM_SOURCE;
}

@Override
BooleanFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return BooleanFieldScript.objectAdapter(parentScriptFactory);
}

}

public static RuntimeField sourceOnly(String name) {
Original file line number Diff line number Diff line change
@@ -46,18 +46,7 @@

public class DateScriptFieldType extends AbstractScriptFieldType<DateFieldScript.LeafFactory> {

public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(name ->
new Builder<>(name, DateFieldScript.CONTEXT) {
private final FieldMapper.Parameter<String> format = FieldMapper.Parameter.stringParam(
"format",
true,
initializerNotSupported(),
null
).setSerializer((b, n, v) -> {
if (v != null && false == v.equals(DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern())) {
b.field(n, v);
}
}, Object::toString).acceptsNull();
public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(Builder::new);

private static class Builder extends AbstractScriptFieldType.Builder<DateFieldScript.Factory> {
private final FieldMapper.Parameter<String> format = FieldMapper.Parameter.stringParam(
@@ -81,20 +70,10 @@ private static class Builder extends AbstractScriptFieldType.Builder<DateFieldSc
if (v != null && false == v.equals(Locale.ROOT)) {
b.field(n, v.toString());
}

@Override
DateFieldScript.Factory getParseFromSourceFactory() {
return DateFieldScript.PARSE_FROM_SOURCE;
}

@Override
DateFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return DateFieldScript.objectAdapter(parentScriptFactory);
}
});
}, Object::toString).acceptsNull();

Builder(String name) {
super(name, DateFieldScript.CONTEXT, DateFieldScript.PARSE_FROM_SOURCE);
super(name, DateFieldScript.CONTEXT);
}

@Override
@@ -112,6 +91,16 @@ AbstractScriptFieldType<?> createFieldType(String name, DateFieldScript.Factory
DateFormatter dateTimeFormatter = DateFormatter.forPattern(pattern).withLocale(locale);
return new DateScriptFieldType(name, factory, dateTimeFormatter, script, meta);
}

@Override
DateFieldScript.Factory getParseFromSourceFactory() {
return DateFieldScript.PARSE_FROM_SOURCE;
}

@Override
DateFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return DateFieldScript.objectAdapter(parentScriptFactory);
}
}

public static RuntimeField sourceOnly(String name, DateFormatter dateTimeFormatter) {
Original file line number Diff line number Diff line change
@@ -35,27 +35,11 @@

public final class DoubleScriptFieldType extends AbstractScriptFieldType<DoubleFieldScript.LeafFactory> {

public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(name ->
new Builder<>(name, DoubleFieldScript.CONTEXT) {
@Override
RuntimeField newRuntimeField(DoubleFieldScript.Factory scriptFactory) {
return runtimeField(name, this, scriptFactory, getScript(), meta());
}

@Override
DoubleFieldScript.Factory getParseFromSourceFactory() {
return DoubleFieldScript.PARSE_FROM_SOURCE;
}

@Override
DoubleFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return DoubleFieldScript.objectAdapter(parentScriptFactory);
}
});
public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(Builder::new);

private static class Builder extends AbstractScriptFieldType.Builder<DoubleFieldScript.Factory> {
Builder(String name) {
super(name, DoubleFieldScript.CONTEXT, DoubleFieldScript.PARSE_FROM_SOURCE);
super(name, DoubleFieldScript.CONTEXT);
}

@Override
@@ -65,6 +49,16 @@ AbstractScriptFieldType<?> createFieldType(String name,
Map<String, String> meta) {
return new DoubleScriptFieldType(name, factory, script, meta);
}

@Override
DoubleFieldScript.Factory getParseFromSourceFactory() {
return DoubleFieldScript.PARSE_FROM_SOURCE;
}

@Override
DoubleFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return DoubleFieldScript.objectAdapter(parentScriptFactory);
}
}

public static RuntimeField sourceOnly(String name) {
Original file line number Diff line number Diff line change
@@ -41,27 +41,11 @@

public final class KeywordScriptFieldType extends AbstractScriptFieldType<StringFieldScript.LeafFactory> {

public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(name ->
new Builder<>(name, StringFieldScript.CONTEXT) {
@Override
RuntimeField newRuntimeField(StringFieldScript.Factory scriptFactory) {
return runtimeField(name, this, scriptFactory, getScript(), meta());
}

@Override
StringFieldScript.Factory getParseFromSourceFactory() {
return StringFieldScript.PARSE_FROM_SOURCE;
}

@Override
StringFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return StringFieldScript.objectAdapter(parentScriptFactory);
}
});
public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(Builder::new);

private static class Builder extends AbstractScriptFieldType.Builder<StringFieldScript.Factory> {
Builder(String name) {
super(name, StringFieldScript.CONTEXT, StringFieldScript.PARSE_FROM_SOURCE);
super(name, StringFieldScript.CONTEXT);
}

@Override
@@ -71,6 +55,16 @@ AbstractScriptFieldType<?> createFieldType(String name,
Map<String, String> meta) {
return new KeywordScriptFieldType(name, factory, script, meta);
}

@Override
StringFieldScript.Factory getParseFromSourceFactory() {
return StringFieldScript.PARSE_FROM_SOURCE;
}

@Override
StringFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return StringFieldScript.objectAdapter(parentScriptFactory);
}
}

public static RuntimeField sourceOnly(String name) {
Original file line number Diff line number Diff line change
@@ -35,33 +35,27 @@

public final class LongScriptFieldType extends AbstractScriptFieldType<LongFieldScript.LeafFactory> {

public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(name ->
new Builder<>(name, LongFieldScript.CONTEXT) {
@Override
RuntimeField newRuntimeField(LongFieldScript.Factory scriptFactory) {
return runtimeField(name, this, scriptFactory, getScript(), meta());
}

@Override
LongFieldScript.Factory getParseFromSourceFactory() {
return LongFieldScript.PARSE_FROM_SOURCE;
}

@Override
LongFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return LongFieldScript.objectAdapter(parentScriptFactory);
}
});
public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(Builder::new);

private static class Builder extends AbstractScriptFieldType.Builder<LongFieldScript.Factory> {
Builder(String name) {
super(name, LongFieldScript.CONTEXT, LongFieldScript.PARSE_FROM_SOURCE);
super(name, LongFieldScript.CONTEXT);
}

@Override
AbstractScriptFieldType<?> createFieldType(String name, LongFieldScript.Factory factory, Script script, Map<String, String> meta) {
return new LongScriptFieldType(name, factory, script, meta);
}

@Override
LongFieldScript.Factory getParseFromSourceFactory() {
return LongFieldScript.PARSE_FROM_SOURCE;
}

@Override
LongFieldScript.Factory getObjectSubfieldFactory(Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory) {
return LongFieldScript.objectAdapter(parentScriptFactory);
}
}

public static RuntimeField sourceOnly(String name) {
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@

package org.elasticsearch.index.mapper;

import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.script.ObjectFieldScript;
import org.elasticsearch.script.Script;
@@ -27,7 +26,6 @@
* A runtime field of type object. Defines a script at the top level, which emits multiple sub-fields.
* The sub-fields are declared within the object in order to be made available to the field_caps and search API.
*/
//TODO find a better name!?
public class ObjectRuntimeField implements RuntimeField {

public static final Parser PARSER = new Parser(name ->
@@ -69,32 +67,16 @@ protected RuntimeField createRuntimeField(MappingParserContext parserContext,
// only print out their leaf field name (which may contain dots!)
Map<String, RuntimeField> runtimeFields = RuntimeField.parseRuntimeFields(fields.getValue(),
parserContext, searchLookup -> factory.newFactory(name, script.get().getParams(), searchLookup), false);
return new ObjectRuntimeField(name, runtimeFields.values(), this);
return new ObjectRuntimeField(name, runtimeFields.values());
}
});

private final String name;
private final Collection<MappedFieldType> subfields;
private final ToXContent toXContent;
private final Collection<RuntimeField> subfields;

ObjectRuntimeField(String name, Collection<RuntimeField> subfields, ToXContent toXContent) {
ObjectRuntimeField(String name, Collection<RuntimeField> subfields) {
this.name = name;
this.subfields = subfields.stream().flatMap(runtimeField -> runtimeField.asMappedFieldTypes().stream())
.collect(Collectors.toList());
this.toXContent = (builder, params) -> {
toXContent.toXContent(builder, params);
builder.startObject("fields2");
for (RuntimeField runtimeField : subfields) {
runtimeField.toXContent(builder, params);
}
builder.endObject();
return builder;
};
}

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

@Override
@@ -103,13 +85,20 @@ public String name() {
}

@Override
public String typeName() {
return "object";
public Collection<MappedFieldType> asMappedFieldTypes() {
return subfields.stream().flatMap(runtimeField -> runtimeField.asMappedFieldTypes().stream()).collect(Collectors.toList());
}

@Override
public Collection<MappedFieldType> asMappedFieldTypes() {
return subfields;
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(name);
builder.field("type", "object");
builder.startObject("fields2");
for (RuntimeField subfield : subfields) {
subfield.toXContent(builder, params);
}
builder.endObject();
return builder;
}

private static Map<String, Object> parseFields(String name, Object fieldsObject) {
Original file line number Diff line number Diff line change
@@ -55,15 +55,6 @@ protected List<Parameter<?>> getParameters() {
return Collections.singletonList(meta);
}

@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;
}

protected abstract RuntimeField createRuntimeField(MappingParserContext parserContext,
Function<SearchLookup, ObjectFieldScript.LeafFactory> parentScriptFactory);

You are viewing a condensed version of this merge commit. You can view the full changes here.