org.opensearch.index.mapper.MetadataFieldMapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opensearch Show documentation
Show all versions of opensearch Show documentation
OpenSearch subproject :server
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.index.mapper;
import org.opensearch.common.Explicit;
import org.opensearch.common.xcontent.support.XContentMapValues;
import org.opensearch.core.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Map;
import java.util.function.Function;
/**
* A mapper for a builtin field containing metadata about a document.
*
* @opensearch.internal
*/
public abstract class MetadataFieldMapper extends ParametrizedFieldMapper {
/**
* Type parser for the field mapper
*
* @opensearch.internal
*/
public interface TypeParser extends Mapper.TypeParser {
@Override
MetadataFieldMapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException;
/**
* Get the default {@link MetadataFieldMapper} to use, if nothing had to be parsed.
* @param fieldType the existing field type for this meta mapper on the current index
* or null if this is the first type being introduced
* @param parserContext context that may be useful to build the field like analyzers
*/
// TODO: remove the fieldType parameter which is only used for bw compat with pre-2.0
// since settings could be modified
MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext parserContext);
}
/**
* Declares an updateable boolean parameter for a metadata field
*
* We need to distinguish between explicit configuration and default value for metadata
* fields, because mapping updates will carry over the previous metadata values if a
* metadata field is not explicitly declared in the update. A standard boolean
* parameter explicitly configured with a default value will not be serialized (as
* we do not serialize default parameters for mapping updates), and as such will be
* ignored by the update merge. Instead, we use an {@link Explicit} object that
* will serialize its value if it has been configured, no matter what the value is.
*/
public static Parameter> updateableBoolParam(
String name,
Function> initializer,
boolean defaultValue
) {
Explicit defaultExplicit = new Explicit<>(defaultValue, false);
return new Parameter<>(
name,
true,
() -> defaultExplicit,
(n, c, o) -> new Explicit<>(XContentMapValues.nodeBooleanValue(o), true),
initializer
).setSerializer((b, n, v) -> b.field(n, v.value()), v -> Boolean.toString(v.value()));
}
/**
* A type parser for an unconfigurable metadata field.
*
* @opensearch.internal
*/
public static class FixedTypeParser implements TypeParser {
final Function mapperParser;
public FixedTypeParser(Function mapperParser) {
this.mapperParser = mapperParser;
}
@Override
public Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException {
throw new MapperParsingException(name + " is not configurable");
}
@Override
public MetadataFieldMapper getDefault(MappedFieldType defaultFieldType, ParserContext parserContext) {
return mapperParser.apply(parserContext);
}
}
/**
* Type parser that is configurable
*
* @opensearch.internal
*/
public static class ConfigurableTypeParser implements TypeParser {
final Function defaultMapperParser;
final Function builderFunction;
public ConfigurableTypeParser(
Function defaultMapperParser,
Function builderFunction
) {
this.defaultMapperParser = defaultMapperParser;
this.builderFunction = builderFunction;
}
@Override
public Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException {
Builder builder = builderFunction.apply(parserContext);
builder.parse(name, parserContext, node);
return builder;
}
@Override
public MetadataFieldMapper getDefault(MappedFieldType defaultFieldType, ParserContext parserContext) {
return defaultMapperParser.apply(parserContext);
}
}
/**
* Base builder for internal metadata fields
*
* @opensearch.internal
*/
public abstract static class Builder extends ParametrizedFieldMapper.Builder {
protected Builder(String name) {
super(name);
}
boolean isConfigured() {
for (Parameter> param : getParameters()) {
if (param.isConfigured()) {
return true;
}
}
return false;
}
@Override
public abstract MetadataFieldMapper build(BuilderContext context);
}
protected MetadataFieldMapper(MappedFieldType mappedFieldType) {
super(mappedFieldType.name(), mappedFieldType, MultiFields.empty(), CopyTo.empty());
}
@Override
public ParametrizedFieldMapper.Builder getMergeBuilder() {
return null; // by default, things can't be configured so we have no builder
}
@Override
public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
MetadataFieldMapper.Builder mergeBuilder = (MetadataFieldMapper.Builder) getMergeBuilder();
if (mergeBuilder == null || mergeBuilder.isConfigured() == false) {
return builder;
}
builder.startObject(simpleName());
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
getMergeBuilder().toXContent(builder, includeDefaults);
return builder.endObject();
}
@Override
protected void parseCreateField(ParseContext context) throws IOException {
throw new MapperParsingException(
"Field [" + name() + "] is a metadata field and cannot be added inside" + " a document. Use the index API request parameters."
);
}
/**
* Called before {@link FieldMapper#parse(ParseContext)} on the {@link RootObjectMapper}.
*/
public void preParse(ParseContext context) throws IOException {
// do nothing
}
/**
* Called after {@link FieldMapper#parse(ParseContext)} on the {@link RootObjectMapper}.
*/
public void postParse(ParseContext context) throws IOException {
// do nothing
}
}