Skip to content

Commit

Permalink
Support for json object within derived field
Browse files Browse the repository at this point in the history
Signed-off-by: Rishabh Maurya <[email protected]>
  • Loading branch information
rishabhmaurya committed May 7, 2024
1 parent 95dcce8 commit d0aa5c0
Show file tree
Hide file tree
Showing 19 changed files with 703 additions and 196 deletions.
35 changes: 32 additions & 3 deletions server/src/main/java/org/opensearch/index/mapper/DerivedField.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,32 +28,54 @@ public class DerivedField implements Writeable, ToXContentFragment {

private final String name;
private final String type;

private final String sourceIndexedField;

private final Script script;

public DerivedField(String name, String type, Script script) {
public DerivedField(String name, String type, Script script, String sourceIndexedField) {
this.name = name;
this.type = type;
this.script = script;
this.sourceIndexedField = sourceIndexedField;
}

public DerivedField(String name, String type, Script script) {
this(name, type, script, null);
}

public DerivedField(StreamInput in) throws IOException {
name = in.readString();
type = in.readString();
script = new Script(in);
if (in.readBoolean()) {
sourceIndexedField = in.readString();
} else {
sourceIndexedField = null;
}
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(name);
out.writeString(type);
script.writeTo(out);
if (sourceIndexedField != null) {
out.writeBoolean(true);
out.writeString(sourceIndexedField);
} else {
out.writeBoolean(false);
}
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
builder.startObject(name);
builder.field("type", type);
builder.field("script", script);
if (sourceIndexedField != null) {
builder.field("source_indexed_field", sourceIndexedField);
}
builder.endObject();
return builder;
}
Expand All @@ -70,9 +92,13 @@ public Script getScript() {
return script;
}

public String getSourceIndexedField() {
return sourceIndexedField;
}

@Override
public int hashCode() {
return Objects.hash(name, type, script);
return Objects.hash(name, type, script, sourceIndexedField);
}

@Override
Expand All @@ -84,7 +110,10 @@ public boolean equals(Object obj) {
return false;
}
DerivedField other = (DerivedField) obj;
return Objects.equals(name, other.name) && Objects.equals(type, other.type) && Objects.equals(script, other.script);
return Objects.equals(name, other.name)
&& Objects.equals(type, other.type)
&& Objects.equals(script, other.script)
&& Objects.equals(sourceIndexedField, other.sourceIndexedField);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@

import org.apache.lucene.index.IndexableField;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.index.analysis.IndexAnalyzers;
import org.opensearch.script.Script;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
Expand All @@ -28,6 +27,8 @@ public class DerivedFieldMapper extends ParametrizedFieldMapper {

public static final String CONTENT_TYPE = "derived";

protected final IndexAnalyzers indexAnalyzers;

private static DerivedFieldMapper toType(FieldMapper in) {
return (DerivedFieldMapper) in;
}
Expand All @@ -38,9 +39,10 @@ private static DerivedFieldMapper toType(FieldMapper in) {
* @opensearch.internal
*/
public static class Builder extends ParametrizedFieldMapper.Builder {
// TODO: The type of parameter may change here if the actual underlying FieldType object is needed
private final Parameter<String> type = Parameter.stringParam("type", false, m -> toType(m).type, "");

private final IndexAnalyzers indexAnalyzers;

private final Parameter<Script> script = new Parameter<>(
"script",
false,
Expand All @@ -49,51 +51,66 @@ public static class Builder extends ParametrizedFieldMapper.Builder {
m -> toType(m).script
).setSerializerCheck((id, ic, value) -> value != null);

public Builder(String name) {
private final Parameter<String> sourceIndexedField = Parameter.stringParam(
"source_indexed_field",
true,
m -> toType(m).sourceIndexedField,
""
);

public Builder(String name, IndexAnalyzers indexAnalyzers) {
super(name);
this.indexAnalyzers = indexAnalyzers;
}

public Builder(DerivedField derivedField) {
public Builder(DerivedField derivedField, IndexAnalyzers indexAnalyzers) {
super(derivedField.getName());
this.type.setValue(derivedField.getType());
this.script.setValue(derivedField.getScript());
this.sourceIndexedField.setValue(derivedField.getSourceIndexedField());
this.indexAnalyzers = indexAnalyzers;
}

@Override
protected List<Parameter<?>> getParameters() {
return Arrays.asList(type, script);
return Arrays.asList(type, script, sourceIndexedField);
}

@Override
public DerivedFieldMapper build(BuilderContext context) {
FieldMapper fieldMapper = DerivedFieldSupportedTypes.getFieldMapperFromType(type.getValue(), name, context);
FieldMapper fieldMapper = DerivedFieldSupportedTypes.getFieldMapperFromType(type.getValue(), name, context, indexAnalyzers);
Function<Object, IndexableField> fieldFunction = DerivedFieldSupportedTypes.getIndexableFieldGeneratorType(
type.getValue(),
name
);
DerivedFieldType ft = new DerivedFieldType(
new DerivedField(buildFullName(context), type.getValue(), script.getValue()),
new DerivedField(buildFullName(context), type.getValue(), script.getValue(), sourceIndexedField.getValue()),
fieldMapper,
fieldFunction
fieldFunction,
indexAnalyzers
);
return new DerivedFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this);
return new DerivedFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this, indexAnalyzers);
}
}

public static final TypeParser PARSER = new TypeParser((n, c) -> new Builder(n));
public static final TypeParser PARSER = new TypeParser((n, c) -> new Builder(n, c.getIndexAnalyzers()));
private final String type;
private final Script script;
private final String sourceIndexedField;

protected DerivedFieldMapper(
String simpleName,
MappedFieldType mappedFieldType,
MultiFields multiFields,
CopyTo copyTo,
Builder builder
Builder builder,
IndexAnalyzers indexAnalyzers
) {
super(simpleName, mappedFieldType, multiFields, copyTo);
this.type = builder.type.getValue();
this.script = builder.script.getValue();
this.sourceIndexedField = builder.sourceIndexedField.getValue();
this.indexAnalyzers = indexAnalyzers;
}

@Override
Expand All @@ -110,7 +127,7 @@ protected void parseCreateField(ParseContext context) throws IOException {

@Override
public ParametrizedFieldMapper.Builder getMergeBuilder() {
return new Builder(simpleName()).init(this);
return new Builder(simpleName(), this.indexAnalyzers).init(this);
}

@Override
Expand All @@ -133,26 +150,4 @@ public Script getScript() {
return script;
}

public static Map<String, DerivedFieldType> getAllDerivedFieldTypeFromObject(
Map<String, Object> derivedFieldObject,
MapperService mapperService
) {
Map<String, DerivedFieldType> derivedFieldTypes = new HashMap<>();
DocumentMapper documentMapper = mapperService.documentMapperParser().parse(DerivedFieldMapper.CONTENT_TYPE, derivedFieldObject);
if (documentMapper != null && documentMapper.mappers() != null) {
for (Mapper mapper : documentMapper.mappers()) {
if (mapper instanceof DerivedFieldMapper) {
DerivedFieldType derivedFieldType = ((DerivedFieldMapper) mapper).fieldType();
derivedFieldTypes.put(derivedFieldType.name(), derivedFieldType);
}
}
}
return derivedFieldTypes;
}

public static DerivedFieldType getDerivedFieldType(DerivedField derivedField, MapperService mapperService) {
BuilderContext builderContext = new Mapper.BuilderContext(mapperService.getIndexSettings().getSettings(), new ContentPath(1));
Builder builder = new Builder(derivedField);
return builder.build(builderContext).fieldType();
}
}
Loading

0 comments on commit d0aa5c0

Please sign in to comment.