All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opensearch.index.mapper.MetadataFieldMapper Maven / Gradle / Ivy

/*
 * 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.annotation.PublicApi;
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.api
 */
@PublicApi(since = "1.0.0")
public abstract class MetadataFieldMapper extends ParametrizedFieldMapper {

    /**
     * Type parser for the field mapper
     *
     * @opensearch.api
     */
    @PublicApi(since = "1.0.0")
    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.api */ @PublicApi(since = "1.0.0") 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 } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy