This commit cuts over all metadata field mappers to parametrized format.
This commit is contained in:
parent
3e2dfc6eac
commit
54279212cf
|
@ -33,4 +33,4 @@ PUT tweets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
// TEST[warning:Index [tweets] uses the deprecated `enabled` setting for `_field_names`. Disabling _field_names is not necessary because it no longer carries a large index overhead. Support for this setting will be removed in a future major version. Please remove it from your mappings and templates.]
|
// TEST[warning:Disabling _field_names is not necessary because it no longer carries a large index overhead. Support for the `enabled` setting will be removed in a future major version. Please remove it from your mappings and templates.]
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class MapperExtrasPlugin extends Plugin implements MapperPlugin, SearchPl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, TypeParser> getMetadataMappers() {
|
public Map<String, TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap(RankFeatureMetaFieldMapper.CONTENT_TYPE, new RankFeatureMetaFieldMapper.TypeParser());
|
return Collections.singletonMap(RankFeatureMetaFieldMapper.CONTENT_TYPE, RankFeatureMetaFieldMapper.PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,16 +19,10 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.index.IndexOptions;
|
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This meta field only exists because rank feature fields index everything into a
|
* This meta field only exists because rank feature fields index everything into a
|
||||||
|
@ -41,48 +35,7 @@ public class RankFeatureMetaFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
public static final String CONTENT_TYPE = "_feature";
|
public static final String CONTENT_TYPE = "_feature";
|
||||||
|
|
||||||
public static class Defaults {
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new RankFeatureMetaFieldMapper());
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
|
||||||
|
|
||||||
static {
|
|
||||||
FIELD_TYPE.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
|
|
||||||
FIELD_TYPE.setTokenized(true);
|
|
||||||
FIELD_TYPE.setStored(false);
|
|
||||||
FIELD_TYPE.setOmitNorms(true);
|
|
||||||
FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
super(NAME, Defaults.FIELD_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RankFeatureMetaFieldMapper build(BuilderContext context) {
|
|
||||||
return new RankFeatureMetaFieldMapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name,
|
|
||||||
Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
final Settings indexSettings = context.mapperService().getIndexSettings().getSettings();
|
|
||||||
if (fieldType != null) {
|
|
||||||
return new RankFeatureMetaFieldMapper();
|
|
||||||
} else {
|
|
||||||
return parse(NAME, Collections.emptyMap(), context)
|
|
||||||
.build(new BuilderContext(indexSettings, new ContentPath(1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class RankFeatureMetaFieldType extends MappedFieldType {
|
public static final class RankFeatureMetaFieldType extends MappedFieldType {
|
||||||
|
|
||||||
|
@ -109,27 +62,23 @@ public class RankFeatureMetaFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private RankFeatureMetaFieldMapper() {
|
private RankFeatureMetaFieldMapper() {
|
||||||
super(Defaults.FIELD_TYPE, RankFeatureMetaFieldType.INSTANCE);
|
super(RankFeatureMetaFieldType.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preParse(ParseContext context) throws IOException {}
|
public void preParse(ParseContext context) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parseCreateField(ParseContext context) throws IOException {
|
protected void parseCreateField(ParseContext context) {
|
||||||
throw new AssertionError("Should never be called");
|
throw new AssertionError("Should never be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postParse(ParseContext context) throws IOException {}
|
public void postParse(ParseContext context) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,88 +19,56 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.mapper.size;
|
package org.elasticsearch.index.mapper.size;
|
||||||
|
|
||||||
import org.apache.lucene.document.FieldType;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
|
||||||
import org.elasticsearch.index.mapper.EnabledAttributeMapper;
|
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
|
||||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.NumberFieldMapper;
|
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberFieldType;
|
||||||
|
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
|
||||||
|
import org.elasticsearch.index.mapper.ParametrizedFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class SizeFieldMapper extends MetadataFieldMapper {
|
public class SizeFieldMapper extends MetadataFieldMapper {
|
||||||
public static final String NAME = "_size";
|
public static final String NAME = "_size";
|
||||||
|
|
||||||
public static class Defaults {
|
private static SizeFieldMapper toType(FieldMapper in) {
|
||||||
public static final EnabledAttributeMapper ENABLED_STATE = EnabledAttributeMapper.UNSET_DISABLED;
|
return (SizeFieldMapper) in;
|
||||||
|
|
||||||
public static final FieldType SIZE_FIELD_TYPE = new FieldType();
|
|
||||||
|
|
||||||
static {
|
|
||||||
SIZE_FIELD_TYPE.setStored(true);
|
|
||||||
SIZE_FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
public static class Builder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
protected EnabledAttributeMapper enabledState = EnabledAttributeMapper.UNSET_DISABLED;
|
private final Parameter<Explicit<Boolean>> enabled
|
||||||
|
= updateableBoolParam("enabled", m -> toType(m).enabled, false);
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
super(NAME, Defaults.SIZE_FIELD_TYPE);
|
super(NAME);
|
||||||
builder = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder enabled(EnabledAttributeMapper enabled) {
|
@Override
|
||||||
this.enabledState = enabled;
|
protected List<Parameter<?>> getParameters() {
|
||||||
return builder;
|
return Collections.singletonList(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SizeFieldMapper build(BuilderContext context) {
|
public SizeFieldMapper build(BuilderContext context) {
|
||||||
return new SizeFieldMapper(fieldType, enabledState,
|
return new SizeFieldMapper(enabled.getValue(), new NumberFieldType(NAME, NumberType.INTEGER));
|
||||||
new NumberFieldMapper.NumberFieldType(NAME, NumberFieldMapper.NumberType.INTEGER));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new ConfigurableTypeParser(
|
||||||
@Override
|
c -> new SizeFieldMapper(new Explicit<>(false, false), new NumberFieldType(NAME, NumberType.INTEGER)),
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
c -> new Builder()
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
);
|
||||||
Builder builder = new Builder();
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String fieldName = entry.getKey();
|
|
||||||
Object fieldNode = entry.getValue();
|
|
||||||
if (fieldName.equals("enabled")) {
|
|
||||||
boolean enabled = XContentMapValues.nodeBooleanValue(fieldNode, name + ".enabled");
|
|
||||||
builder.enabled(enabled ? EnabledAttributeMapper.ENABLED : EnabledAttributeMapper.DISABLED);
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private final Explicit<Boolean> enabled;
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new SizeFieldMapper(Defaults.SIZE_FIELD_TYPE, Defaults.ENABLED_STATE,
|
|
||||||
new NumberFieldMapper.NumberFieldType(NAME, NumberFieldMapper.NumberType.INTEGER));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnabledAttributeMapper enabledState;
|
private SizeFieldMapper(Explicit<Boolean> enabled, MappedFieldType mappedFieldType) {
|
||||||
|
super(mappedFieldType);
|
||||||
private SizeFieldMapper(FieldType fieldType, EnabledAttributeMapper enabled,
|
this.enabled = enabled;
|
||||||
MappedFieldType mappedFieldType) {
|
|
||||||
super(fieldType, mappedFieldType);
|
|
||||||
this.enabledState = enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,7 +77,7 @@ public class SizeFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean enabled() {
|
public boolean enabled() {
|
||||||
return this.enabledState.enabled;
|
return this.enabled.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -129,37 +97,15 @@ public class SizeFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parseCreateField(ParseContext context) {
|
protected void parseCreateField(ParseContext context) {
|
||||||
if (!enabledState.enabled) {
|
if (enabled.value() == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int value = context.sourceToParse().source().length();
|
final int value = context.sourceToParse().source().length();
|
||||||
boolean indexed = fieldType().isSearchable();
|
context.doc().addAll(NumberType.INTEGER.createFields(name(), value, true, true, true));
|
||||||
boolean docValued = fieldType().hasDocValues();
|
|
||||||
boolean stored = fieldType.stored();
|
|
||||||
context.doc().addAll(NumberFieldMapper.NumberType.INTEGER.createFields(name(), value, indexed, docValued, stored));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
|
return new Builder().init(this);
|
||||||
|
|
||||||
// all are defaults, no need to write it at all
|
|
||||||
if (!includeDefaults && enabledState == Defaults.ENABLED_STATE) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
builder.startObject(contentType());
|
|
||||||
if (includeDefaults || enabledState != Defaults.ENABLED_STATE) {
|
|
||||||
builder.field("enabled", enabledState.enabled);
|
|
||||||
}
|
|
||||||
builder.endObject();
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
|
||||||
SizeFieldMapper sizeFieldMapperMergeWith = (SizeFieldMapper) other;
|
|
||||||
if (sizeFieldMapperMergeWith.enabledState != enabledState && !sizeFieldMapperMergeWith.enabledState.unset()) {
|
|
||||||
this.enabledState = sizeFieldMapperMergeWith.enabledState;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,18 +19,18 @@
|
||||||
|
|
||||||
package org.elasticsearch.plugin.mapper;
|
package org.elasticsearch.plugin.mapper;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.size.SizeFieldMapper;
|
import org.elasticsearch.index.mapper.size.SizeFieldMapper;
|
||||||
import org.elasticsearch.plugins.MapperPlugin;
|
import org.elasticsearch.plugins.MapperPlugin;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class MapperSizePlugin extends Plugin implements MapperPlugin {
|
public class MapperSizePlugin extends Plugin implements MapperPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap(SizeFieldMapper.NAME, new SizeFieldMapper.TypeParser());
|
return Collections.singletonMap(SizeFieldMapper.NAME, SizeFieldMapper.PARSER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.common;
|
package org.elasticsearch.common;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds a value that is either:
|
* Holds a value that is either:
|
||||||
* a) set implicitly e.g. through some default value
|
* a) set implicitly e.g. through some default value
|
||||||
|
@ -54,4 +56,18 @@ public class Explicit<T> {
|
||||||
public boolean explicit() {
|
public boolean explicit() {
|
||||||
return this.explicit;
|
return this.explicit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Explicit<?> explicit1 = (Explicit<?>) o;
|
||||||
|
return explicit == explicit1.explicit &&
|
||||||
|
Objects.equals(value, explicit1.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(value, explicit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,12 @@ import org.apache.lucene.document.FieldType;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Noop mapper that ensures that mappings created in 6x that explicitly disable the _all field
|
* Noop mapper that ensures that mappings created in 6x that explicitly disable the _all field
|
||||||
|
@ -52,51 +50,37 @@ public class AllFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
private static AllFieldMapper toType(FieldMapper in) {
|
||||||
private boolean disableExplicit = false;
|
return (AllFieldMapper) in;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder(MappedFieldType existing) {
|
public static class Builder extends MetadataFieldMapper.Builder {
|
||||||
super(NAME, Defaults.FIELD_TYPE);
|
|
||||||
builder = this;
|
private final Parameter<Explicit<Boolean>> enabled = updateableBoolParam("enabled", m -> toType(m).enabled, false);
|
||||||
|
|
||||||
|
public Builder() {
|
||||||
|
super(NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Builder setDisableExplicit() {
|
@Override
|
||||||
this.disableExplicit = true;
|
protected List<Parameter<?>> getParameters() {
|
||||||
return this;
|
return Collections.singletonList(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AllFieldMapper build(BuilderContext context) {
|
public AllFieldMapper build(BuilderContext context) {
|
||||||
return new AllFieldMapper(disableExplicit);
|
if (enabled.getValue().value()) {
|
||||||
}
|
throw new IllegalArgumentException("[_all] is disabled in this version.");
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
Builder builder = new Builder(parserContext.mapperService().fieldType(NAME));
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String fieldName = entry.getKey();
|
|
||||||
if (fieldName.equals("enabled")) {
|
|
||||||
boolean enabled = XContentMapValues.nodeBooleanValue(entry.getValue(), "enabled");
|
|
||||||
if (enabled) {
|
|
||||||
throw new IllegalArgumentException("[_all] is disabled in this version.");
|
|
||||||
}
|
|
||||||
builder.setDisableExplicit();
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return builder;
|
return new AllFieldMapper(enabled.getValue());
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new AllFieldMapper(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final TypeParser PARSER = new ConfigurableTypeParser(
|
||||||
|
c -> new AllFieldMapper(new Explicit<>(true, false)),
|
||||||
|
c -> new Builder()
|
||||||
|
);
|
||||||
|
|
||||||
static final class AllFieldType extends StringFieldType {
|
static final class AllFieldType extends StringFieldType {
|
||||||
AllFieldType() {
|
AllFieldType() {
|
||||||
super(NAME, false, false, TextSearchInfo.NONE, Collections.emptyMap());
|
super(NAME, false, false, TextSearchInfo.NONE, Collections.emptyMap());
|
||||||
|
@ -113,15 +97,15 @@ public class AllFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean disableExplicit;
|
private final Explicit<Boolean> enabled;
|
||||||
|
|
||||||
private AllFieldMapper(boolean disableExplicit) {
|
private AllFieldMapper(Explicit<Boolean> enabled) {
|
||||||
super(Defaults.FIELD_TYPE, new AllFieldType());
|
super(new AllFieldType());
|
||||||
this.disableExplicit = disableExplicit;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preParse(ParseContext context) throws IOException {
|
public void preParse(ParseContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,7 +121,6 @@ public class AllFieldMapper extends MetadataFieldMapper {
|
||||||
@Override
|
@Override
|
||||||
protected void parseCreateField(ParseContext context) throws IOException {
|
protected void parseCreateField(ParseContext context) throws IOException {
|
||||||
// noop mapper
|
// noop mapper
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -145,16 +128,4 @@ public class AllFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
|
|
||||||
if (includeDefaults || disableExplicit) {
|
|
||||||
builder.startObject(CONTENT_TYPE);
|
|
||||||
if (disableExplicit) {
|
|
||||||
builder.field("enabled", false);
|
|
||||||
}
|
|
||||||
builder.endObject();
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ public class CompletionFieldMapper extends ParametrizedFieldMapper {
|
||||||
b.startArray(n);
|
b.startArray(n);
|
||||||
c.toXContent(b, ToXContent.EMPTY_PARAMS);
|
c.toXContent(b, ToXContent.EMPTY_PARAMS);
|
||||||
b.endArray();
|
b.endArray();
|
||||||
});
|
}, ContextMappings::toString);
|
||||||
private final Parameter<Integer> maxInputLength = Parameter.intParam("max_input_length", true,
|
private final Parameter<Integer> maxInputLength = Parameter.intParam("max_input_length", true,
|
||||||
m -> toType(m).maxInputLength, Defaults.DEFAULT_MAX_INPUT_LENGTH)
|
m -> toType(m).maxInputLength, Defaults.DEFAULT_MAX_INPUT_LENGTH)
|
||||||
.addDeprecatedName("max_input_len")
|
.addDeprecatedName("max_input_len")
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class DocumentMapper implements ToXContentFragment {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder put(MetadataFieldMapper.Builder<?> mapper) {
|
public Builder put(MetadataFieldMapper.Builder mapper) {
|
||||||
MetadataFieldMapper metadataMapper = mapper.build(builderContext);
|
MetadataFieldMapper metadataMapper = mapper.build(builderContext);
|
||||||
metadataMappers.put(metadataMapper.getClass(), metadataMapper);
|
metadataMappers.put(metadataMapper.getClass(), metadataMapper);
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.elasticsearch.index.mapper;
|
|
||||||
|
|
||||||
public enum EnabledAttributeMapper {
|
|
||||||
ENABLED(true), UNSET_ENABLED(true), DISABLED(false), UNSET_DISABLED(false);
|
|
||||||
|
|
||||||
public final boolean enabled;
|
|
||||||
|
|
||||||
EnabledAttributeMapper(boolean enabled) {
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean unset() {
|
|
||||||
return this == UNSET_DISABLED || this == UNSET_ENABLED;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,10 +26,8 @@ import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -37,7 +35,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapper that indexes the field names of a document under <code>_field_names</code>. This mapper is typically useful in order
|
* A mapper that indexes the field names of a document under <code>_field_names</code>. This mapper is typically useful in order
|
||||||
|
@ -54,10 +51,15 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
public static final String CONTENT_TYPE = "_field_names";
|
public static final String CONTENT_TYPE = "_field_names";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
|
return new Builder(indexVersionCreated).init(this);
|
||||||
|
}
|
||||||
|
|
||||||
public static class Defaults {
|
public static class Defaults {
|
||||||
public static final String NAME = FieldNamesFieldMapper.NAME;
|
public static final String NAME = FieldNamesFieldMapper.NAME;
|
||||||
|
|
||||||
public static final boolean ENABLED = true;
|
public static final Explicit<Boolean> ENABLED = new Explicit<>(true, false);
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
public static final FieldType FIELD_TYPE = new FieldType();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -69,69 +71,53 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
private static FieldNamesFieldMapper toType(FieldMapper in) {
|
||||||
private boolean enabled = Defaults.ENABLED;
|
return (FieldNamesFieldMapper) in;
|
||||||
|
}
|
||||||
|
|
||||||
Builder() {
|
public static final String ENABLED_DEPRECATION_MESSAGE =
|
||||||
super(Defaults.NAME, Defaults.FIELD_TYPE);
|
"Disabling _field_names is not necessary because it no longer carries a large index overhead. Support for the `enabled` " +
|
||||||
|
"setting will be removed in a future major version. Please remove it from your mappings and templates.";
|
||||||
|
|
||||||
|
|
||||||
|
static class Builder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
|
private final Parameter<Explicit<Boolean>> enabled
|
||||||
|
= updateableBoolParam("enabled", m -> toType(m).enabled, Defaults.ENABLED.value());
|
||||||
|
|
||||||
|
private final Version indexVersionCreated;
|
||||||
|
|
||||||
|
Builder(Version indexVersionCreated) {
|
||||||
|
super(Defaults.NAME);
|
||||||
|
this.indexVersionCreated = indexVersionCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
Builder enabled(boolean enabled) {
|
protected List<Parameter<?>> getParameters() {
|
||||||
this.enabled = enabled;
|
return Collections.singletonList(enabled);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FieldNamesFieldMapper build(BuilderContext context) {
|
public FieldNamesFieldMapper build(BuilderContext context) {
|
||||||
FieldNamesFieldType fieldNamesFieldType = new FieldNamesFieldType();
|
if (enabled.getValue().explicit()) {
|
||||||
fieldNamesFieldType.setEnabled(enabled);
|
deprecationLogger.deprecatedAndMaybeLog("field_names_enabled_parameter", ENABLED_DEPRECATION_MESSAGE);
|
||||||
return new FieldNamesFieldMapper(fieldType, fieldNamesFieldType);
|
}
|
||||||
|
FieldNamesFieldType fieldNamesFieldType = new FieldNamesFieldType(enabled.getValue().value());
|
||||||
|
return new FieldNamesFieldMapper(enabled.getValue(), indexVersionCreated, fieldNamesFieldType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new ConfigurableTypeParser(
|
||||||
|
c -> new FieldNamesFieldMapper(Defaults.ENABLED, c.indexVersionCreated(), new FieldNamesFieldType(Defaults.ENABLED.value())),
|
||||||
public static final String ENABLED_DEPRECATION_MESSAGE = "Index [{}] uses the deprecated `enabled` setting for `_field_names`. "
|
c -> new Builder(c.indexVersionCreated())
|
||||||
+ "Disabling _field_names is not necessary because it no longer carries a large index overhead. Support for this setting "
|
);
|
||||||
+ "will be removed in a future major version. Please remove it from your mappings and templates.";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String fieldName = entry.getKey();
|
|
||||||
Object fieldNode = entry.getValue();
|
|
||||||
if (fieldName.equals("enabled")) {
|
|
||||||
String indexName = parserContext.mapperService().index().getName();
|
|
||||||
deprecationLogger.deprecatedAndMaybeLog("field_names_enabled_parameter", ENABLED_DEPRECATION_MESSAGE, indexName);
|
|
||||||
builder.enabled(XContentMapValues.nodeBooleanValue(fieldNode, name + ".enabled"));
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
final Settings indexSettings = context.mapperService().getIndexSettings().getSettings();
|
|
||||||
if (fieldType != null) {
|
|
||||||
return new FieldNamesFieldMapper(Defaults.FIELD_TYPE, fieldType);
|
|
||||||
} else {
|
|
||||||
return parse(NAME, Collections.emptyMap(), context)
|
|
||||||
.build(new BuilderContext(indexSettings, new ContentPath(1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class FieldNamesFieldType extends TermBasedFieldType {
|
public static final class FieldNamesFieldType extends TermBasedFieldType {
|
||||||
|
|
||||||
private boolean enabled = Defaults.ENABLED;
|
private final boolean enabled;
|
||||||
|
|
||||||
public FieldNamesFieldType() {
|
public FieldNamesFieldType(boolean enabled) {
|
||||||
super(Defaults.NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
|
super(Defaults.NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
|
||||||
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,10 +125,6 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
@ -164,8 +146,13 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldNamesFieldMapper(FieldType fieldType, MappedFieldType mappedFieldType) {
|
private final Explicit<Boolean> enabled;
|
||||||
super(fieldType, mappedFieldType);
|
private final Version indexVersionCreated;
|
||||||
|
|
||||||
|
private FieldNamesFieldMapper(Explicit<Boolean> enabled, Version indexVersionCreated, FieldNamesFieldType mappedFieldType) {
|
||||||
|
super(mappedFieldType);
|
||||||
|
this.enabled = enabled;
|
||||||
|
this.indexVersionCreated = indexVersionCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -261,21 +248,4 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
|
|
||||||
|
|
||||||
if (includeDefaults == false && fieldType().isEnabled() == Defaults.ENABLED) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.startObject(NAME);
|
|
||||||
if (includeDefaults || fieldType().isEnabled() != Defaults.ENABLED) {
|
|
||||||
builder.field("enabled", fieldType().isEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.endObject();
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
import org.elasticsearch.common.util.BigArrays;
|
import org.elasticsearch.common.util.BigArrays;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
|
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
|
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
|
||||||
|
@ -55,7 +54,6 @@ import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapper for the _id field. It does nothing since _id is neither indexed nor
|
* A mapper for the _id field. It does nothing since _id is neither indexed nor
|
||||||
|
@ -78,7 +76,6 @@ public class IdFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
public static final FieldType FIELD_TYPE = new FieldType();
|
||||||
public static final FieldType NESTED_FIELD_TYPE;
|
public static final FieldType NESTED_FIELD_TYPE;
|
||||||
public static final MappedFieldType MAPPED_FIELD_TYPE = new IdFieldType();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
FIELD_TYPE.setTokenized(false);
|
FIELD_TYPE.setTokenized(false);
|
||||||
|
@ -97,18 +94,7 @@ public class IdFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new IdFieldMapper());
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
throw new MapperParsingException(NAME + " is not configurable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new IdFieldMapper(Defaults.FIELD_TYPE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class IdFieldType extends TermBasedFieldType {
|
static final class IdFieldType extends TermBasedFieldType {
|
||||||
|
|
||||||
|
@ -263,8 +249,8 @@ public class IdFieldMapper extends MetadataFieldMapper {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdFieldMapper(FieldType fieldType) {
|
private IdFieldMapper() {
|
||||||
super(fieldType, new IdFieldType());
|
super(new IdFieldType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -274,10 +260,8 @@ public class IdFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parseCreateField(ParseContext context) throws IOException {
|
protected void parseCreateField(ParseContext context) throws IOException {
|
||||||
if (fieldType.indexOptions() != IndexOptions.NONE || fieldType.stored()) {
|
BytesRef id = Uid.encodeId(context.sourceToParse().id());
|
||||||
BytesRef id = Uid.encodeId(context.sourceToParse().id());
|
context.doc().add(new Field(NAME, id, Defaults.FIELD_TYPE));
|
||||||
context.doc().add(new Field(NAME, id, fieldType));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -285,8 +269,4 @@ public class IdFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,10 @@ import org.apache.lucene.document.FieldType;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.TermRangeQuery;
|
import org.apache.lucene.search.TermRangeQuery;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A field mapper that records fields that have been ignored because they were malformed.
|
* A field mapper that records fields that have been ignored because they were malformed.
|
||||||
|
@ -54,30 +52,7 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new IgnoredFieldMapper());
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
super(Defaults.NAME, Defaults.FIELD_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IgnoredFieldMapper build(BuilderContext context) {
|
|
||||||
return new IgnoredFieldMapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new IgnoredFieldMapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class IgnoredFieldType extends StringFieldType {
|
public static final class IgnoredFieldType extends StringFieldType {
|
||||||
|
|
||||||
|
@ -104,7 +79,7 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private IgnoredFieldMapper() {
|
private IgnoredFieldMapper() {
|
||||||
super(Defaults.FIELD_TYPE, IgnoredFieldType.INSTANCE);
|
super(IgnoredFieldType.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,7 +99,7 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
|
||||||
@Override
|
@Override
|
||||||
protected void parseCreateField(ParseContext context) throws IOException {
|
protected void parseCreateField(ParseContext context) throws IOException {
|
||||||
for (String field : context.getIgnoredFields()) {
|
for (String field : context.getIgnoredFields()) {
|
||||||
context.doc().add(new Field(NAME, field, fieldType));
|
context.doc().add(new Field(NAME, field, Defaults.FIELD_TYPE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,9 +108,4 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,8 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.index.IndexOptions;
|
|
||||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
import org.elasticsearch.index.fielddata.plain.ConstantIndexFieldData;
|
import org.elasticsearch.index.fielddata.plain.ConstantIndexFieldData;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
@ -31,7 +28,6 @@ import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
public class IndexFieldMapper extends MetadataFieldMapper {
|
public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
|
@ -40,44 +36,7 @@ public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
public static final String CONTENT_TYPE = "_index";
|
public static final String CONTENT_TYPE = "_index";
|
||||||
|
|
||||||
public static class Defaults {
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new IndexFieldMapper());
|
||||||
public static final String NAME = IndexFieldMapper.NAME;
|
|
||||||
|
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
|
||||||
|
|
||||||
static {
|
|
||||||
FIELD_TYPE.setIndexOptions(IndexOptions.NONE);
|
|
||||||
FIELD_TYPE.setTokenized(false);
|
|
||||||
FIELD_TYPE.setStored(false);
|
|
||||||
FIELD_TYPE.setOmitNorms(true);
|
|
||||||
FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
super(Defaults.NAME, Defaults.FIELD_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IndexFieldMapper build(BuilderContext context) {
|
|
||||||
return new IndexFieldMapper(fieldType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
throw new MapperParsingException(NAME + " is not configurable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new IndexFieldMapper(Defaults.FIELD_TYPE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class IndexFieldType extends ConstantFieldType {
|
static final class IndexFieldType extends ConstantFieldType {
|
||||||
|
|
||||||
|
@ -109,8 +68,8 @@ public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexFieldMapper(FieldType fieldType) {
|
public IndexFieldMapper() {
|
||||||
super(fieldType, IndexFieldType.INSTANCE);
|
super(IndexFieldType.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,8 +83,4 @@ public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.network.InetAddresses;
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
|
import org.elasticsearch.common.network.NetworkAddress;
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
import org.elasticsearch.index.fielddata.ScriptDocValues;
|
import org.elasticsearch.index.fielddata.ScriptDocValues;
|
||||||
import org.elasticsearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
|
import org.elasticsearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
|
||||||
|
@ -72,7 +73,7 @@ public class IpFieldMapper extends ParametrizedFieldMapper {
|
||||||
} else {
|
} else {
|
||||||
b.field(f, InetAddresses.toAddrString(v));
|
b.field(f, InetAddresses.toAddrString(v));
|
||||||
}
|
}
|
||||||
});
|
}, NetworkAddress::format);
|
||||||
|
|
||||||
private final Parameter<Map<String, String>> meta = Parameter.metaParam();
|
private final Parameter<Map<String, String>> meta = Parameter.metaParam();
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,24 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.FieldType;
|
import org.elasticsearch.common.Explicit;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mapper for a builtin field containing metadata about a document.
|
* A mapper for a builtin field containing metadata about a document.
|
||||||
*/
|
*/
|
||||||
public abstract class MetadataFieldMapper extends FieldMapper {
|
public abstract class MetadataFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
public interface TypeParser extends Mapper.TypeParser {
|
public interface TypeParser extends Mapper.TypeParser {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
MetadataFieldMapper.Builder parse(String name, Map<String, Object> node,
|
||||||
ParserContext parserContext) throws MapperParsingException;
|
ParserContext parserContext) throws MapperParsingException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,25 +50,109 @@ public abstract class MetadataFieldMapper extends FieldMapper {
|
||||||
MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext parserContext);
|
MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
/**
|
||||||
public abstract static class Builder<T extends Builder<T>> extends FieldMapper.Builder<T> {
|
* Declares an updateable boolean parameter for a metadata field
|
||||||
public Builder(String name, FieldType fieldType) {
|
*
|
||||||
super(name, fieldType);
|
* 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<Explicit<Boolean>> updateableBoolParam(String name, Function<FieldMapper, Explicit<Boolean>> initializer,
|
||||||
|
boolean defaultValue) {
|
||||||
|
Explicit<Boolean> 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.
|
||||||
|
*/
|
||||||
|
public static class FixedTypeParser implements TypeParser {
|
||||||
|
|
||||||
|
final Function<ParserContext, MetadataFieldMapper> mapperParser;
|
||||||
|
|
||||||
|
public FixedTypeParser(Function<ParserContext, MetadataFieldMapper> mapperParser) {
|
||||||
|
this.mapperParser = mapperParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T index(boolean index) {
|
public Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||||
if (index == false) {
|
throw new MapperParsingException(name + " is not configurable");
|
||||||
throw new IllegalArgumentException("Metadata fields must be indexed");
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public MetadataFieldMapper getDefault(MappedFieldType defaultFieldType, ParserContext parserContext) {
|
||||||
|
return mapperParser.apply(parserContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConfigurableTypeParser implements TypeParser {
|
||||||
|
|
||||||
|
final Function<ParserContext, MetadataFieldMapper> defaultMapperParser;
|
||||||
|
final Function<ParserContext, Builder> builderFunction;
|
||||||
|
|
||||||
|
public ConfigurableTypeParser(Function<ParserContext, MetadataFieldMapper> defaultMapperParser,
|
||||||
|
Function<ParserContext, Builder> builderFunction) {
|
||||||
|
this.defaultMapperParser = defaultMapperParser;
|
||||||
|
this.builderFunction = builderFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||||
|
Builder builder = builderFunction.apply(parserContext);
|
||||||
|
builder.parse(name, parserContext, node);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetadataFieldMapper getDefault(MappedFieldType defaultFieldType, ParserContext parserContext) {
|
||||||
|
return defaultMapperParser.apply(parserContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
public abstract MetadataFieldMapper build(BuilderContext context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MetadataFieldMapper(FieldType fieldType, MappedFieldType mappedFieldType) {
|
protected MetadataFieldMapper(MappedFieldType mappedFieldType) {
|
||||||
super(mappedFieldType.name(), fieldType, mappedFieldType, MultiFields.empty(), CopyTo.empty());
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +172,4 @@ public abstract class MetadataFieldMapper extends FieldMapper {
|
||||||
throw new UnsupportedOperationException("The " + typeName() + " field is not stored in _source.");
|
throw new UnsupportedOperationException("The " + typeName() + " field is not stored in _source.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) { }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,9 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
ParametrizedFieldMapper.Builder builder = getMergeBuilder();
|
ParametrizedFieldMapper.Builder builder = getMergeBuilder();
|
||||||
|
if (builder == null) {
|
||||||
|
return (ParametrizedFieldMapper) mergeWith;
|
||||||
|
}
|
||||||
Conflicts conflicts = new Conflicts(name());
|
Conflicts conflicts = new Conflicts(name());
|
||||||
builder.merge((FieldMapper) mergeWith, conflicts);
|
builder.merge((FieldMapper) mergeWith, conflicts);
|
||||||
conflicts.check();
|
conflicts.check();
|
||||||
|
@ -108,11 +111,6 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
// TODO remove when everything is parametrized
|
// TODO remove when everything is parametrized
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return super.toXContent(builder, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
protected final void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||||
builder.field("type", contentType());
|
builder.field("type", contentType());
|
||||||
|
@ -143,6 +141,7 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
private boolean acceptsNull = false;
|
private boolean acceptsNull = false;
|
||||||
private Consumer<T> validator = null;
|
private Consumer<T> validator = null;
|
||||||
private Serializer<T> serializer = XContentBuilder::field;
|
private Serializer<T> serializer = XContentBuilder::field;
|
||||||
|
private Function<T, String> conflictSerializer = Object::toString;
|
||||||
private T value;
|
private T value;
|
||||||
private boolean isSet;
|
private boolean isSet;
|
||||||
|
|
||||||
|
@ -186,6 +185,10 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isConfigured() {
|
||||||
|
return isSet && Objects.equals(value, defaultValue.get()) == false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows the parameter to accept a {@code null} value
|
* Allows the parameter to accept a {@code null} value
|
||||||
*/
|
*/
|
||||||
|
@ -216,8 +219,9 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
/**
|
/**
|
||||||
* Configure a custom serializer for this parameter
|
* Configure a custom serializer for this parameter
|
||||||
*/
|
*/
|
||||||
public Parameter<T> setSerializer(Serializer<T> serializer) {
|
public Parameter<T> setSerializer(Serializer<T> serializer, Function<T, String> conflictSerializer) {
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
|
this.conflictSerializer = conflictSerializer;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,15 +241,16 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
|
|
||||||
private void merge(FieldMapper toMerge, Conflicts conflicts) {
|
private void merge(FieldMapper toMerge, Conflicts conflicts) {
|
||||||
T value = initializer.apply(toMerge);
|
T value = initializer.apply(toMerge);
|
||||||
if (updateable == false && isSet && Objects.equals(this.value, value) == false) {
|
T current = getValue();
|
||||||
conflicts.addConflict(name, this.value.toString(), value.toString());
|
if (updateable == false && Objects.equals(current, value) == false) {
|
||||||
|
conflicts.addConflict(name, conflictSerializer.apply(current), conflictSerializer.apply(value));
|
||||||
} else {
|
} else {
|
||||||
setValue(value);
|
setValue(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toXContent(XContentBuilder builder, boolean includeDefaults) throws IOException {
|
private void toXContent(XContentBuilder builder, boolean includeDefaults) throws IOException {
|
||||||
if (includeDefaults || Objects.equals(getValue(), defaultValue.get()) == false) {
|
if (includeDefaults || isConfigured()) {
|
||||||
serializer.serialize(builder, name, getValue());
|
serializer.serialize(builder, name, getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,6 +304,20 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
(n, c, o) -> XContentMapValues.nodeStringValue(o), initializer);
|
(n, c, o) -> XContentMapValues.nodeStringValue(o), initializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Parameter<List<String>> stringArrayParam(String name, boolean updateable,
|
||||||
|
Function<FieldMapper, List<String>> initializer, List<String> defaultValue) {
|
||||||
|
return new Parameter<>(name, updateable, () -> defaultValue,
|
||||||
|
(n, c, o) -> {
|
||||||
|
List<Object> values = (List<Object>) o;
|
||||||
|
List<String> strValues = new ArrayList<>();
|
||||||
|
for (Object item : values) {
|
||||||
|
strValues.add(item.toString());
|
||||||
|
}
|
||||||
|
return strValues;
|
||||||
|
}, initializer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a parameter that takes an analyzer name
|
* Defines a parameter that takes an analyzer name
|
||||||
* @param name the parameter name
|
* @param name the parameter name
|
||||||
|
@ -316,7 +335,7 @@ public abstract class ParametrizedFieldMapper extends FieldMapper {
|
||||||
throw new IllegalArgumentException("analyzer [" + analyzerName + "] has not been configured in mappings");
|
throw new IllegalArgumentException("analyzer [" + analyzerName + "] has not been configured in mappings");
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}, initializer).setSerializer((b, n, v) -> b.field(n, v.name()));
|
}, initializer).setSerializer((b, n, v) -> b.field(n, v.name()), NamedAnalyzer::name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,26 +26,25 @@ import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.TermQuery;
|
import org.apache.lucene.search.TermQuery;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class RoutingFieldMapper extends MetadataFieldMapper {
|
public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
public static final String NAME = "_routing";
|
public static final String NAME = "_routing";
|
||||||
public static final String CONTENT_TYPE = "_routing";
|
public static final String CONTENT_TYPE = "_routing";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
|
return new Builder().init(this);
|
||||||
|
}
|
||||||
|
|
||||||
public static class Defaults {
|
public static class Defaults {
|
||||||
public static final String NAME = "_routing";
|
|
||||||
|
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
public static final FieldType FIELD_TYPE = new FieldType();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
FIELD_TYPE.setIndexOptions(IndexOptions.DOCS);
|
FIELD_TYPE.setIndexOptions(IndexOptions.DOCS);
|
||||||
FIELD_TYPE.setTokenized(false);
|
FIELD_TYPE.setTokenized(false);
|
||||||
|
@ -57,53 +56,33 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
public static final boolean REQUIRED = false;
|
public static final boolean REQUIRED = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
private static RoutingFieldMapper toType(FieldMapper in) {
|
||||||
|
return (RoutingFieldMapper) in;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean required = Defaults.REQUIRED;
|
public static class Builder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
public Builder() {
|
final Parameter<Boolean> required = Parameter.boolParam("required", false, m -> toType(m).required, Defaults.REQUIRED);
|
||||||
super(Defaults.NAME, Defaults.FIELD_TYPE);
|
|
||||||
|
protected Builder() {
|
||||||
|
super(NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder required(boolean required) {
|
@Override
|
||||||
this.required = required;
|
protected List<Parameter<?>> getParameters() {
|
||||||
return builder;
|
return Collections.singletonList(required);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RoutingFieldMapper build(BuilderContext context) {
|
public RoutingFieldMapper build(BuilderContext context) {
|
||||||
return new RoutingFieldMapper(fieldType, required);
|
return new RoutingFieldMapper(required.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new ConfigurableTypeParser(
|
||||||
@Override
|
c -> new RoutingFieldMapper(Defaults.REQUIRED),
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
c -> new Builder()
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
);
|
||||||
Builder builder = new Builder();
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String fieldName = entry.getKey();
|
|
||||||
Object fieldNode = entry.getValue();
|
|
||||||
if (fieldName.equals("required")) {
|
|
||||||
builder.required(XContentMapValues.nodeBooleanValue(fieldNode, name + ".required"));
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
final Settings indexSettings = context.mapperService().getIndexSettings().getSettings();
|
|
||||||
if (fieldType != null) {
|
|
||||||
return new RoutingFieldMapper(Defaults.FIELD_TYPE, Defaults.REQUIRED);
|
|
||||||
} else {
|
|
||||||
return parse(NAME, Collections.emptyMap(), context)
|
|
||||||
.build(new BuilderContext(indexSettings, new ContentPath(1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class RoutingFieldType extends StringFieldType {
|
static final class RoutingFieldType extends StringFieldType {
|
||||||
|
|
||||||
|
@ -127,8 +106,8 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
private final boolean required;
|
private final boolean required;
|
||||||
|
|
||||||
private RoutingFieldMapper(FieldType fieldType, boolean required) {
|
private RoutingFieldMapper(boolean required) {
|
||||||
super(fieldType, RoutingFieldType.INSTANCE);
|
super(RoutingFieldType.INSTANCE);
|
||||||
this.required = required;
|
this.required = required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,10 +131,8 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
protected void parseCreateField(ParseContext context) throws IOException {
|
protected void parseCreateField(ParseContext context) throws IOException {
|
||||||
String routing = context.sourceToParse().routing();
|
String routing = context.sourceToParse().routing();
|
||||||
if (routing != null) {
|
if (routing != null) {
|
||||||
if (fieldType.indexOptions() != IndexOptions.NONE || fieldType.stored()) {
|
context.doc().add(new Field(fieldType().name(), routing, Defaults.FIELD_TYPE));
|
||||||
context.doc().add(new Field(fieldType().name(), routing, fieldType));
|
createFieldNamesField(context);
|
||||||
createFieldNamesField(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,19 +141,4 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
|
|
||||||
|
|
||||||
// if all are defaults, no sense to write it at all
|
|
||||||
if (!includeDefaults && required == Defaults.REQUIRED) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
builder.startObject(CONTENT_TYPE);
|
|
||||||
if (includeDefaults || required != Defaults.REQUIRED) {
|
|
||||||
builder.field("required", required);
|
|
||||||
}
|
|
||||||
builder.endObject();
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,14 @@
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.document.LongPoint;
|
import org.apache.lucene.document.LongPoint;
|
||||||
import org.apache.lucene.document.NumericDocValuesField;
|
import org.apache.lucene.document.NumericDocValuesField;
|
||||||
import org.apache.lucene.index.DocValuesType;
|
|
||||||
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
||||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
import org.elasticsearch.index.fielddata.IndexNumericFieldData.NumericType;
|
import org.elasticsearch.index.fielddata.IndexNumericFieldData.NumericType;
|
||||||
import org.elasticsearch.index.fielddata.plain.SortedNumericIndexFieldData;
|
import org.elasticsearch.index.fielddata.plain.SortedNumericIndexFieldData;
|
||||||
|
@ -42,7 +38,6 @@ import org.elasticsearch.index.seqno.SequenceNumbers;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,33 +89,12 @@ public class SeqNoFieldMapper extends MetadataFieldMapper {
|
||||||
public static final String PRIMARY_TERM_NAME = "_primary_term";
|
public static final String PRIMARY_TERM_NAME = "_primary_term";
|
||||||
public static final String TOMBSTONE_NAME = "_tombstone";
|
public static final String TOMBSTONE_NAME = "_tombstone";
|
||||||
|
|
||||||
public static class Defaults {
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new SeqNoFieldMapper());
|
||||||
public static final String NAME = SeqNoFieldMapper.NAME;
|
|
||||||
public static final MappedFieldType MAPPED_FIELD_TYPE = new SeqNoFieldType();
|
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
|
||||||
|
|
||||||
static {
|
|
||||||
FIELD_TYPE.setDocValuesType(DocValuesType.SORTED);
|
|
||||||
FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node, ParserContext parserContext)
|
|
||||||
throws MapperParsingException {
|
|
||||||
throw new MapperParsingException(NAME + " is not configurable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
final Settings indexSettings = context.mapperService().getIndexSettings().getSettings();
|
|
||||||
return new SeqNoFieldMapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class SeqNoFieldType extends SimpleMappedFieldType {
|
static final class SeqNoFieldType extends SimpleMappedFieldType {
|
||||||
|
|
||||||
|
private static final SeqNoFieldType INSTANCE = new SeqNoFieldType();
|
||||||
|
|
||||||
SeqNoFieldType() {
|
SeqNoFieldType() {
|
||||||
super(NAME, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
|
super(NAME, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
@ -202,7 +176,7 @@ public class SeqNoFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SeqNoFieldMapper() {
|
public SeqNoFieldMapper() {
|
||||||
super(Defaults.FIELD_TYPE, Defaults.MAPPED_FIELD_TYPE);
|
super(SeqNoFieldType.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -252,9 +226,4 @@ public class SeqNoFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.util.CollectionUtils;
|
import org.elasticsearch.common.util.CollectionUtils;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
@ -43,7 +42,6 @@ import org.elasticsearch.index.query.QueryShardException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -71,78 +69,36 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
private static SourceFieldMapper toType(FieldMapper in) {
|
||||||
|
return (SourceFieldMapper) in;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean enabled = Defaults.ENABLED;
|
public static class Builder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
private String[] includes = null;
|
private final Parameter<Boolean> enabled = Parameter.boolParam("enabled", false, m -> toType(m).enabled, Defaults.ENABLED);
|
||||||
private String[] excludes = null;
|
private final Parameter<List<String>> includes
|
||||||
|
= Parameter.stringArrayParam("includes", false, m -> Arrays.asList(toType(m).includes), Collections.emptyList());
|
||||||
|
private final Parameter<List<String>> excludes
|
||||||
|
= Parameter.stringArrayParam("excludes", false, m -> Arrays.asList(toType(m).excludes), Collections.emptyList());
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
super(Defaults.NAME, new FieldType(Defaults.FIELD_TYPE));
|
super(Defaults.NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder enabled(boolean enabled) {
|
@Override
|
||||||
this.enabled = enabled;
|
protected List<Parameter<?>> getParameters() {
|
||||||
return this;
|
return Arrays.asList(enabled, includes, excludes);
|
||||||
}
|
|
||||||
|
|
||||||
public Builder includes(String[] includes) {
|
|
||||||
this.includes = includes;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder excludes(String[] excludes) {
|
|
||||||
this.excludes = excludes;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SourceFieldMapper build(BuilderContext context) {
|
public SourceFieldMapper build(BuilderContext context) {
|
||||||
return new SourceFieldMapper(enabled, includes, excludes);
|
return new SourceFieldMapper(enabled.getValue(),
|
||||||
|
includes.getValue().toArray(new String[0]),
|
||||||
|
excludes.getValue().toArray(new String[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new ConfigurableTypeParser(c -> new SourceFieldMapper(), c -> new Builder());
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String fieldName = entry.getKey();
|
|
||||||
Object fieldNode = entry.getValue();
|
|
||||||
if (fieldName.equals("enabled")) {
|
|
||||||
builder.enabled(XContentMapValues.nodeBooleanValue(fieldNode, name + ".enabled"));
|
|
||||||
iterator.remove();
|
|
||||||
} else if (fieldName.equals("includes")) {
|
|
||||||
List<Object> values = (List<Object>) fieldNode;
|
|
||||||
String[] includes = new String[values.size()];
|
|
||||||
for (int i = 0; i < includes.length; i++) {
|
|
||||||
includes[i] = values.get(i).toString();
|
|
||||||
}
|
|
||||||
builder.includes(includes);
|
|
||||||
iterator.remove();
|
|
||||||
} else if (fieldName.equals("excludes")) {
|
|
||||||
List<Object> values = (List<Object>) fieldNode;
|
|
||||||
String[] excludes = new String[values.size()];
|
|
||||||
for (int i = 0; i < excludes.length; i++) {
|
|
||||||
excludes[i] = values.get(i).toString();
|
|
||||||
}
|
|
||||||
builder.excludes(excludes);
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
final Settings indexSettings = context.mapperService().getIndexSettings().getSettings();
|
|
||||||
return new SourceFieldMapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class SourceFieldType extends MappedFieldType {
|
static final class SourceFieldType extends MappedFieldType {
|
||||||
|
|
||||||
|
@ -177,32 +133,23 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
||||||
private final String[] excludes;
|
private final String[] excludes;
|
||||||
|
|
||||||
private SourceFieldMapper() {
|
private SourceFieldMapper() {
|
||||||
this(Defaults.ENABLED, null, null);
|
this(Defaults.ENABLED, Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceFieldMapper(boolean enabled, String[] includes, String[] excludes) {
|
private SourceFieldMapper(boolean enabled, String[] includes, String[] excludes) {
|
||||||
super(Defaults.FIELD_TYPE, SourceFieldType.INSTANCE); // Only stored.
|
super(SourceFieldType.INSTANCE); // Only stored.
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
this.includes = includes;
|
this.includes = includes;
|
||||||
this.excludes = excludes;
|
this.excludes = excludes;
|
||||||
final boolean filtered = CollectionUtils.isEmpty(includes) == false || CollectionUtils.isEmpty(excludes) == false;
|
final boolean filtered = CollectionUtils.isEmpty(includes) == false || CollectionUtils.isEmpty(excludes) == false;
|
||||||
this.filter = enabled && filtered && fieldType.stored() ? XContentMapValues.filter(includes, excludes) : null;
|
this.filter = enabled && filtered ? XContentMapValues.filter(includes, excludes) : null;
|
||||||
this.complete = enabled && includes == null && excludes == null;
|
this.complete = enabled && CollectionUtils.isEmpty(includes) && CollectionUtils.isEmpty(excludes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean enabled() {
|
public boolean enabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] excludes() {
|
|
||||||
return this.excludes != null ? this.excludes : Strings.EMPTY_ARRAY;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] includes() {
|
|
||||||
return this.includes != null ? this.includes : Strings.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isComplete() {
|
public boolean isComplete() {
|
||||||
return complete;
|
return complete;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +185,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public BytesReference applyFilters(@Nullable BytesReference originalSource, @Nullable XContentType contentType) throws IOException {
|
public BytesReference applyFilters(@Nullable BytesReference originalSource, @Nullable XContentType contentType) throws IOException {
|
||||||
if (enabled && fieldType.stored() && originalSource != null) {
|
if (enabled && originalSource != null) {
|
||||||
// Percolate and tv APIs may not set the source and that is ok, because these APIs will not index any data
|
// Percolate and tv APIs may not set the source and that is ok, because these APIs will not index any data
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
// we don't update the context source if we filter, we want to keep it as is...
|
// we don't update the context source if we filter, we want to keep it as is...
|
||||||
|
@ -264,46 +211,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
|
return new Builder().init(this);
|
||||||
|
|
||||||
// all are defaults, no need to write it at all
|
|
||||||
if (!includeDefaults && enabled == Defaults.ENABLED && includes == null && excludes == null) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
builder.startObject(contentType());
|
|
||||||
if (includeDefaults || enabled != Defaults.ENABLED) {
|
|
||||||
builder.field("enabled", enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includes != null) {
|
|
||||||
builder.array("includes", includes);
|
|
||||||
} else if (includeDefaults) {
|
|
||||||
builder.array("includes", Strings.EMPTY_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludes != null) {
|
|
||||||
builder.array("excludes", excludes);
|
|
||||||
} else if (includeDefaults) {
|
|
||||||
builder.array("excludes", Strings.EMPTY_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.endObject();
|
|
||||||
return builder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
|
||||||
SourceFieldMapper sourceMergeWith = (SourceFieldMapper) other;
|
|
||||||
if (this.enabled != sourceMergeWith.enabled) {
|
|
||||||
conflicts.add("Cannot update enabled setting for [_source]");
|
|
||||||
}
|
|
||||||
if (Arrays.equals(includes(), sourceMergeWith.includes()) == false) {
|
|
||||||
conflicts.add("Cannot update includes setting for [_source]");
|
|
||||||
}
|
|
||||||
if (Arrays.equals(excludes(), sourceMergeWith.excludes()) == false) {
|
|
||||||
conflicts.add("Cannot update excludes setting for [_source]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,6 @@ import org.apache.lucene.search.WildcardQuery;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.common.lucene.search.Queries;
|
import org.elasticsearch.common.lucene.search.Queries;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.IndexSettings;
|
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
import org.elasticsearch.index.fielddata.plain.ConstantIndexFieldData;
|
import org.elasticsearch.index.fielddata.plain.ConstantIndexFieldData;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
@ -52,7 +50,6 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -64,35 +61,18 @@ public class TypeFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
public static final String CONTENT_TYPE = "_type";
|
public static final String CONTENT_TYPE = "_type";
|
||||||
|
|
||||||
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new TypeFieldMapper());
|
||||||
|
|
||||||
public static class Defaults {
|
public static class Defaults {
|
||||||
public static final String NAME = TypeFieldMapper.NAME;
|
|
||||||
|
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
public static final FieldType NESTED_FIELD_TYPE = new FieldType();
|
||||||
static {
|
|
||||||
FIELD_TYPE.setIndexOptions(IndexOptions.NONE);
|
|
||||||
FIELD_TYPE.setTokenized(false);
|
|
||||||
FIELD_TYPE.setStored(false);
|
|
||||||
FIELD_TYPE.setOmitNorms(true);
|
|
||||||
FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final FieldType NESTED_FIELD_TYPE = new FieldType(FIELD_TYPE);
|
|
||||||
static {
|
static {
|
||||||
NESTED_FIELD_TYPE.setIndexOptions(IndexOptions.DOCS);
|
NESTED_FIELD_TYPE.setIndexOptions(IndexOptions.DOCS);
|
||||||
}
|
NESTED_FIELD_TYPE.setTokenized(false);
|
||||||
}
|
NESTED_FIELD_TYPE.setStored(false);
|
||||||
|
NESTED_FIELD_TYPE.setOmitNorms(true);
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
NESTED_FIELD_TYPE.freeze();
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
throw new MapperParsingException(NAME + " is not configurable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
final IndexSettings indexSettings = context.mapperService().getIndexSettings();
|
|
||||||
return new TypeFieldMapper(Defaults.FIELD_TYPE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,8 +255,8 @@ public class TypeFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeFieldMapper(FieldType fieldType) {
|
private TypeFieldMapper() {
|
||||||
super(fieldType, new TypeFieldType());
|
super(new TypeFieldType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -305,9 +285,4 @@ public class TypeFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,20 +20,15 @@
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.document.NumericDocValuesField;
|
import org.apache.lucene.document.NumericDocValuesField;
|
||||||
import org.apache.lucene.index.DocValuesType;
|
|
||||||
import org.apache.lucene.index.IndexOptions;
|
|
||||||
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.index.mapper.ParseContext.Document;
|
import org.elasticsearch.index.mapper.ParseContext.Document;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.index.query.QueryShardException;
|
import org.elasticsearch.index.query.QueryShardException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/** Mapper for the _version field. */
|
/** Mapper for the _version field. */
|
||||||
public class VersionFieldMapper extends MetadataFieldMapper {
|
public class VersionFieldMapper extends MetadataFieldMapper {
|
||||||
|
@ -41,31 +36,7 @@ public class VersionFieldMapper extends MetadataFieldMapper {
|
||||||
public static final String NAME = "_version";
|
public static final String NAME = "_version";
|
||||||
public static final String CONTENT_TYPE = "_version";
|
public static final String CONTENT_TYPE = "_version";
|
||||||
|
|
||||||
public static class Defaults {
|
public static final TypeParser PARSER = new FixedTypeParser(c -> new VersionFieldMapper());
|
||||||
|
|
||||||
public static final String NAME = VersionFieldMapper.NAME;
|
|
||||||
public static final FieldType FIELD_TYPE = new FieldType();
|
|
||||||
public static final MappedFieldType MAPPED_FIELD_TYPE = new VersionFieldType();
|
|
||||||
|
|
||||||
static {
|
|
||||||
FIELD_TYPE.setDocValuesType(DocValuesType.NUMERIC);
|
|
||||||
FIELD_TYPE.setIndexOptions(IndexOptions.NONE);
|
|
||||||
FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
throw new MapperParsingException(NAME + " is not configurable");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new VersionFieldMapper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class VersionFieldType extends MappedFieldType {
|
static final class VersionFieldType extends MappedFieldType {
|
||||||
|
|
||||||
|
@ -92,7 +63,7 @@ public class VersionFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private VersionFieldMapper() {
|
private VersionFieldMapper() {
|
||||||
super(Defaults.FIELD_TYPE, Defaults.MAPPED_FIELD_TYPE);
|
super(VersionFieldType.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -129,9 +100,4 @@ public class VersionFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,18 +153,18 @@ public class IndicesModule extends AbstractModule {
|
||||||
// Use a LinkedHashMap for metadataMappers because iteration order matters
|
// Use a LinkedHashMap for metadataMappers because iteration order matters
|
||||||
builtInMetadataMappers = new LinkedHashMap<>();
|
builtInMetadataMappers = new LinkedHashMap<>();
|
||||||
// _ignored first so that we always load it, even if only _id is requested
|
// _ignored first so that we always load it, even if only _id is requested
|
||||||
builtInMetadataMappers.put(IgnoredFieldMapper.NAME, new IgnoredFieldMapper.TypeParser());
|
builtInMetadataMappers.put(IgnoredFieldMapper.NAME, IgnoredFieldMapper.PARSER);
|
||||||
// ID second so it will be the first (if no ignored fields) stored field to load
|
// ID second so it will be the first (if no ignored fields) stored field to load
|
||||||
// (so will benefit from "fields: []" early termination
|
// (so will benefit from "fields: []" early termination
|
||||||
builtInMetadataMappers.put(IdFieldMapper.NAME, new IdFieldMapper.TypeParser());
|
builtInMetadataMappers.put(IdFieldMapper.NAME, IdFieldMapper.PARSER);
|
||||||
builtInMetadataMappers.put(RoutingFieldMapper.NAME, new RoutingFieldMapper.TypeParser());
|
builtInMetadataMappers.put(RoutingFieldMapper.NAME, RoutingFieldMapper.PARSER);
|
||||||
builtInMetadataMappers.put(IndexFieldMapper.NAME, new IndexFieldMapper.TypeParser());
|
builtInMetadataMappers.put(IndexFieldMapper.NAME, IndexFieldMapper.PARSER);
|
||||||
builtInMetadataMappers.put(SourceFieldMapper.NAME, new SourceFieldMapper.TypeParser());
|
builtInMetadataMappers.put(SourceFieldMapper.NAME, SourceFieldMapper.PARSER);
|
||||||
builtInMetadataMappers.put(TypeFieldMapper.NAME, new TypeFieldMapper.TypeParser());
|
builtInMetadataMappers.put(TypeFieldMapper.NAME, TypeFieldMapper.PARSER);
|
||||||
builtInMetadataMappers.put(VersionFieldMapper.NAME, new VersionFieldMapper.TypeParser());
|
builtInMetadataMappers.put(VersionFieldMapper.NAME, VersionFieldMapper.PARSER);
|
||||||
builtInMetadataMappers.put(SeqNoFieldMapper.NAME, new SeqNoFieldMapper.TypeParser());
|
builtInMetadataMappers.put(SeqNoFieldMapper.NAME, SeqNoFieldMapper.PARSER);
|
||||||
//_field_names must be added last so that it has a chance to see all the other mappers
|
//_field_names must be added last so that it has a chance to see all the other mappers
|
||||||
builtInMetadataMappers.put(FieldNamesFieldMapper.NAME, new FieldNamesFieldMapper.TypeParser());
|
builtInMetadataMappers.put(FieldNamesFieldMapper.NAME, FieldNamesFieldMapper.PARSER);
|
||||||
return Collections.unmodifiableMap(builtInMetadataMappers);
|
return Collections.unmodifiableMap(builtInMetadataMappers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public final class MapperRegistry {
|
||||||
this.metadataMapperParsers = Collections.unmodifiableMap(new LinkedHashMap<>(metadataMapperParsers));
|
this.metadataMapperParsers = Collections.unmodifiableMap(new LinkedHashMap<>(metadataMapperParsers));
|
||||||
// add the _all field mapper for indices created in 6x
|
// add the _all field mapper for indices created in 6x
|
||||||
Map<String, MetadataFieldMapper.TypeParser> metadata6x = new LinkedHashMap<>();
|
Map<String, MetadataFieldMapper.TypeParser> metadata6x = new LinkedHashMap<>();
|
||||||
metadata6x.put(AllFieldMapper.NAME, new AllFieldMapper.TypeParser());
|
metadata6x.put(AllFieldMapper.NAME, AllFieldMapper.PARSER);
|
||||||
metadata6x.putAll(metadataMapperParsers);
|
metadata6x.putAll(metadataMapperParsers);
|
||||||
this.metadataMapperParsers6x = Collections.unmodifiableMap(metadata6x);
|
this.metadataMapperParsers6x = Collections.unmodifiableMap(metadata6x);
|
||||||
this.fieldFilter = fieldFilter;
|
this.fieldFilter = fieldFilter;
|
||||||
|
|
|
@ -43,6 +43,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.elasticsearch.search.suggest.completion.context.ContextMapping.FIELD_NAME;
|
import static org.elasticsearch.search.suggest.completion.context.ContextMapping.FIELD_NAME;
|
||||||
import static org.elasticsearch.search.suggest.completion.context.ContextMapping.FIELD_TYPE;
|
import static org.elasticsearch.search.suggest.completion.context.ContextMapping.FIELD_TYPE;
|
||||||
|
@ -297,4 +298,9 @@ public class ContextMappings implements ToXContent, Iterable<ContextMapping<?>>
|
||||||
ContextMappings other = ((ContextMappings) obj);
|
ContextMappings other = ((ContextMappings) obj);
|
||||||
return contextMappings.equals(other.contextMappings);
|
return contextMappings.equals(other.contextMappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return contextMappings.stream().map(ContextMapping::toString).collect(Collectors.joining(",", "[", "]"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.cluster.metadata;
|
package org.elasticsearch.cluster.metadata;
|
||||||
|
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
@ -35,17 +34,18 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.index.Index;
|
import org.elasticsearch.index.Index;
|
||||||
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
import org.elasticsearch.index.mapper.Mapper;
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||||
|
import org.elasticsearch.index.mapper.ParametrizedFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
import org.elasticsearch.index.mapper.TextSearchInfo;
|
import org.elasticsearch.index.mapper.TextSearchInfo;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
@ -75,6 +75,7 @@ import java.util.stream.Collectors;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static org.elasticsearch.cluster.metadata.MetadataIndexTemplateService.DEFAULT_TIMESTAMP_FIELD;
|
import static org.elasticsearch.cluster.metadata.MetadataIndexTemplateService.DEFAULT_TIMESTAMP_FIELD;
|
||||||
import static org.elasticsearch.common.settings.Settings.builder;
|
import static org.elasticsearch.common.settings.Settings.builder;
|
||||||
|
import static org.elasticsearch.index.mapper.ParametrizedFieldMapper.Parameter;
|
||||||
import static org.elasticsearch.indices.ShardLimitValidatorTests.createTestShardLimitService;
|
import static org.elasticsearch.indices.ShardLimitValidatorTests.createTestShardLimitService;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.CoreMatchers.containsStringIgnoringCase;
|
import static org.hamcrest.CoreMatchers.containsStringIgnoringCase;
|
||||||
|
@ -1550,75 +1551,77 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap("_data_stream_timestamp", new MetadataFieldMapper.TypeParser() {
|
return Collections.singletonMap("_data_stream_timestamp", new MetadataFieldMapper.ConfigurableTypeParser(
|
||||||
|
c -> new MetadataTimestampFieldMapper(false),
|
||||||
|
c -> new MetadataTimestampFieldBuilder())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MetadataTimestampFieldMapper toType(FieldMapper in) {
|
||||||
|
return (MetadataTimestampFieldMapper) in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MetadataTimestampFieldBuilder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
|
private final Parameter<Boolean> enabled = Parameter.boolParam("enabled", true, m -> toType(m).enabled, false);
|
||||||
|
|
||||||
|
protected MetadataTimestampFieldBuilder() {
|
||||||
|
super("_data_stream_timestamp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ParametrizedFieldMapper.Parameter<?>> getParameters() {
|
||||||
|
return Collections.singletonList(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetadataFieldMapper build(Mapper.BuilderContext context) {
|
||||||
|
return new MetadataTimestampFieldMapper(enabled.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MetadataTimestampFieldMapper extends MetadataFieldMapper {
|
||||||
|
final boolean enabled;
|
||||||
|
|
||||||
|
public MetadataTimestampFieldMapper(boolean enabled) {
|
||||||
|
super(new MappedFieldType("_data_stream_timestamp", false, false, TextSearchInfo.NONE, Collections.emptyMap()) {
|
||||||
@Override
|
@Override
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name,
|
public String typeName() {
|
||||||
Map<String, Object> node,
|
return "_data_stream_timestamp";
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
Boolean enabled = (Boolean) node.remove("enabled");
|
|
||||||
return new MetadataFieldMapper.Builder(name, new FieldType()) {
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper build(Mapper.BuilderContext context) {
|
|
||||||
return newInstance(enabled);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext parserContext) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
return newInstance(null);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetadataFieldMapper newInstance(Boolean enabled) {
|
@Override
|
||||||
FieldType fieldType = new FieldType();
|
public Query existsQuery(QueryShardContext context) {
|
||||||
fieldType.freeze();
|
return null;
|
||||||
MappedFieldType mappedFieldType =
|
|
||||||
new MappedFieldType("_data_stream_timestamp", false, false, TextSearchInfo.NONE, Collections.emptyMap()) {
|
|
||||||
@Override
|
|
||||||
public String typeName() {
|
|
||||||
return "_data_stream_timestamp";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Query existsQuery(QueryShardContext context) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return new MetadataFieldMapper(fieldType, mappedFieldType) {
|
|
||||||
@Override
|
|
||||||
public void preParse(ParseContext context) throws IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void parseCreateField(ParseContext context) throws IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
if (enabled == null) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.startObject(simpleName());
|
|
||||||
builder.field("enabled", enabled);
|
|
||||||
return builder.endObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String contentType() {
|
|
||||||
return "_data_stream_timestamp";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
|
return new MetadataTimestampFieldBuilder().init(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preParse(ParseContext context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseCreateField(ParseContext context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String contentType() {
|
||||||
|
return "_data_stream_timestamp";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class ExternalFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
IndexService indexService = createIndex("test", settings);
|
IndexService indexService = createIndex("test", settings);
|
||||||
MapperRegistry mapperRegistry = new MapperRegistry(
|
MapperRegistry mapperRegistry = new MapperRegistry(
|
||||||
singletonMap(ExternalMapperPlugin.EXTERNAL, new ExternalMapper.TypeParser(ExternalMapperPlugin.EXTERNAL, "foo")),
|
singletonMap(ExternalMapperPlugin.EXTERNAL, new ExternalMapper.TypeParser(ExternalMapperPlugin.EXTERNAL, "foo")),
|
||||||
singletonMap(ExternalMetadataMapper.CONTENT_TYPE, new ExternalMetadataMapper.TypeParser()), MapperPlugin.NOOP_FIELD_FILTER);
|
singletonMap(ExternalMetadataMapper.CONTENT_TYPE, ExternalMetadataMapper.PARSER), MapperPlugin.NOOP_FIELD_FILTER);
|
||||||
|
|
||||||
Supplier<QueryShardContext> queryShardContext = () -> {
|
Supplier<QueryShardContext> queryShardContext = () -> {
|
||||||
return indexService.newQueryShardContext(0, null, () -> { throw new UnsupportedOperationException(); }, null);
|
return indexService.newQueryShardContext(0, null, () -> { throw new UnsupportedOperationException(); }, null);
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class ExternalMapperPlugin extends Plugin implements MapperPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap(ExternalMetadataMapper.CONTENT_TYPE, new ExternalMetadataMapper.TypeParser());
|
return Collections.singletonMap(ExternalMetadataMapper.CONTENT_TYPE, ExternalMetadataMapper.PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,12 @@
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.Field.Store;
|
import org.apache.lucene.document.Field.Store;
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.document.StringField;
|
import org.apache.lucene.document.StringField;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
|
|
||||||
public class ExternalMetadataMapper extends MetadataFieldMapper {
|
public class ExternalMetadataMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ public class ExternalMetadataMapper extends MetadataFieldMapper {
|
||||||
static final String FIELD_VALUE = "true";
|
static final String FIELD_VALUE = "true";
|
||||||
|
|
||||||
protected ExternalMetadataMapper() {
|
protected ExternalMetadataMapper() {
|
||||||
super(new FieldType(), new BooleanFieldMapper.BooleanFieldType(FIELD_NAME));
|
super(new BooleanFieldMapper.BooleanFieldType(FIELD_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,11 +47,6 @@ public class ExternalMetadataMapper extends MetadataFieldMapper {
|
||||||
return Collections.emptyIterator();
|
return Collections.emptyIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
return builder.startObject(CONTENT_TYPE).endObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
@ -68,10 +61,15 @@ public class ExternalMetadataMapper extends MetadataFieldMapper {
|
||||||
context.doc().add(new StringField(FIELD_NAME, FIELD_VALUE, Store.YES));
|
context.doc().add(new StringField(FIELD_NAME, FIELD_VALUE, Store.YES));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
public static class Builder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
protected Builder() {
|
protected Builder() {
|
||||||
super(FIELD_NAME, new FieldType());
|
super(FIELD_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<Parameter<?>> getParameters() {
|
||||||
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,19 +79,6 @@ public class ExternalMetadataMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new ConfigurableTypeParser(c -> new ExternalMetadataMapper(), c -> new Builder());
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node,
|
|
||||||
ParserContext parserContext) throws MapperParsingException {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return new ExternalMetadataMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,10 +81,10 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
FieldNamesFieldMapper fieldNamesMapper = docMapper.metadataMapper(FieldNamesFieldMapper.class);
|
FieldNamesFieldMapper fieldNamesMapper = docMapper.metadataMapper(FieldNamesFieldMapper.class);
|
||||||
assertFalse(fieldNamesMapper.fieldType().hasDocValues());
|
assertFalse(fieldNamesMapper.fieldType().hasDocValues());
|
||||||
|
|
||||||
assertEquals(IndexOptions.DOCS, fieldNamesMapper.fieldType.indexOptions());
|
assertEquals(IndexOptions.DOCS, FieldNamesFieldMapper.Defaults.FIELD_TYPE.indexOptions());
|
||||||
assertFalse(fieldNamesMapper.fieldType.tokenized());
|
assertFalse(FieldNamesFieldMapper.Defaults.FIELD_TYPE.tokenized());
|
||||||
assertFalse(fieldNamesMapper.fieldType.stored());
|
assertFalse(FieldNamesFieldMapper.Defaults.FIELD_TYPE.stored());
|
||||||
assertTrue(fieldNamesMapper.fieldType.omitNorms());
|
assertTrue(FieldNamesFieldMapper.Defaults.FIELD_TYPE.omitNorms());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInjectIntoDocDuringParsing() throws Exception {
|
public void testInjectIntoDocDuringParsing() throws Exception {
|
||||||
|
@ -124,7 +124,7 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
XContentType.JSON));
|
XContentType.JSON));
|
||||||
|
|
||||||
assertFieldNames(set("field"), doc);
|
assertFieldNames(set("field"), doc);
|
||||||
assertWarnings(FieldNamesFieldMapper.TypeParser.ENABLED_DEPRECATION_MESSAGE.replace("{}", "test"));
|
assertWarnings(FieldNamesFieldMapper.ENABLED_DEPRECATION_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDisabled() throws Exception {
|
public void testDisabled() throws Exception {
|
||||||
|
@ -144,7 +144,7 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
XContentType.JSON));
|
XContentType.JSON));
|
||||||
|
|
||||||
assertNull(doc.rootDoc().get("_field_names"));
|
assertNull(doc.rootDoc().get("_field_names"));
|
||||||
assertWarnings(FieldNamesFieldMapper.TypeParser.ENABLED_DEPRECATION_MESSAGE.replace("{}", "test"));
|
assertWarnings(FieldNamesFieldMapper.ENABLED_DEPRECATION_MESSAGE.replace("{}", "test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMergingMappings() throws Exception {
|
public void testMergingMappings() throws Exception {
|
||||||
|
@ -164,6 +164,6 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
DocumentMapper mapperEnabled
|
DocumentMapper mapperEnabled
|
||||||
= mapperService.merge("type", new CompressedXContent(enabledMapping), MapperService.MergeReason.MAPPING_UPDATE);
|
= mapperService.merge("type", new CompressedXContent(enabledMapping), MapperService.MergeReason.MAPPING_UPDATE);
|
||||||
assertTrue(mapperEnabled.metadataMapper(FieldNamesFieldMapper.class).fieldType().isEnabled());
|
assertTrue(mapperEnabled.metadataMapper(FieldNamesFieldMapper.class).fieldType().isEnabled());
|
||||||
assertWarnings(FieldNamesFieldMapper.TypeParser.ENABLED_DEPRECATION_MESSAGE.replace("{}", "test"));
|
assertWarnings(FieldNamesFieldMapper.ENABLED_DEPRECATION_MESSAGE.replace("{}", "test"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class FieldNamesFieldTypeTests extends ESTestCase {
|
||||||
|
|
||||||
public void testTermQuery() {
|
public void testTermQuery() {
|
||||||
|
|
||||||
FieldNamesFieldMapper.FieldNamesFieldType fieldNamesFieldType = new FieldNamesFieldMapper.FieldNamesFieldType();
|
FieldNamesFieldMapper.FieldNamesFieldType fieldNamesFieldType = new FieldNamesFieldMapper.FieldNamesFieldType(true);
|
||||||
KeywordFieldMapper.KeywordFieldType fieldType = new KeywordFieldMapper.KeywordFieldType("field_name");
|
KeywordFieldMapper.KeywordFieldType fieldType = new KeywordFieldMapper.KeywordFieldType("field_name");
|
||||||
|
|
||||||
Settings settings = settings(Version.CURRENT).build();
|
Settings settings = settings(Version.CURRENT).build();
|
||||||
|
@ -52,12 +52,12 @@ public class FieldNamesFieldTypeTests extends ESTestCase {
|
||||||
QueryShardContext queryShardContext = new QueryShardContext(0,
|
QueryShardContext queryShardContext = new QueryShardContext(0,
|
||||||
indexSettings, BigArrays.NON_RECYCLING_INSTANCE, null, null, mapperService,
|
indexSettings, BigArrays.NON_RECYCLING_INSTANCE, null, null, mapperService,
|
||||||
null, null, null, null, null, null, () -> 0L, null, null, () -> true, null);
|
null, null, null, null, null, null, () -> 0L, null, null, () -> true, null);
|
||||||
fieldNamesFieldType.setEnabled(true);
|
Query termQuery = fieldNamesFieldType.termQuery("field_name", queryShardContext);
|
||||||
Query termQuery = fieldNamesFieldType.termQuery("field_name", queryShardContext);
|
|
||||||
assertEquals(new TermQuery(new Term(FieldNamesFieldMapper.CONTENT_TYPE, "field_name")), termQuery);
|
assertEquals(new TermQuery(new Term(FieldNamesFieldMapper.CONTENT_TYPE, "field_name")), termQuery);
|
||||||
assertWarnings("terms query on the _field_names field is deprecated and will be removed, use exists query instead");
|
assertWarnings("terms query on the _field_names field is deprecated and will be removed, use exists query instead");
|
||||||
fieldNamesFieldType.setEnabled(false);
|
|
||||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> fieldNamesFieldType.termQuery("field_name", null));
|
FieldNamesFieldMapper.FieldNamesFieldType unsearchable = new FieldNamesFieldMapper.FieldNamesFieldType(false);
|
||||||
|
IllegalStateException e = expectThrows(IllegalStateException.class, () -> unsearchable.termQuery("field_name", null));
|
||||||
assertEquals("Cannot run [exists] queries if the [_field_names] field is disabled", e.getMessage());
|
assertEquals("Cannot run [exists] queries if the [_field_names] field is disabled", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,12 +99,12 @@ public class ParametrizedMapperTests extends ESSingleNodeTestCase {
|
||||||
final Parameter<String> variable
|
final Parameter<String> variable
|
||||||
= Parameter.stringParam("variable", true, m -> toType(m).variable, "default").acceptsNull();
|
= Parameter.stringParam("variable", true, m -> toType(m).variable, "default").acceptsNull();
|
||||||
final Parameter<StringWrapper> wrapper
|
final Parameter<StringWrapper> wrapper
|
||||||
= new Parameter<>("wrapper", true, () -> new StringWrapper("default"),
|
= new Parameter<>("wrapper", false, () -> new StringWrapper("default"),
|
||||||
(n, c, o) -> {
|
(n, c, o) -> {
|
||||||
if (o == null) return null;
|
if (o == null) return null;
|
||||||
return new StringWrapper(o.toString());
|
return new StringWrapper(o.toString());
|
||||||
},
|
},
|
||||||
m -> toType(m).wrapper).setSerializer((b, n, v) -> b.field(n, v.name));
|
m -> toType(m).wrapper).setSerializer((b, n, v) -> b.field(n, v.name), v -> "wrapper_" + v.name);
|
||||||
final Parameter<Integer> intValue = Parameter.intParam("int_value", true, m -> toType(m).intValue, 5)
|
final Parameter<Integer> intValue = Parameter.intParam("int_value", true, m -> toType(m).intValue, 5)
|
||||||
.setValidator(n -> {
|
.setValidator(n -> {
|
||||||
if (n > 50) {
|
if (n > 50) {
|
||||||
|
@ -112,7 +112,7 @@ public class ParametrizedMapperTests extends ESSingleNodeTestCase {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
final Parameter<NamedAnalyzer> analyzer
|
final Parameter<NamedAnalyzer> analyzer
|
||||||
= Parameter.analyzerParam("analyzer", true, m -> toType(m).analyzer, () -> Lucene.KEYWORD_ANALYZER);
|
= Parameter.analyzerParam("analyzer", false, m -> toType(m).analyzer, () -> Lucene.KEYWORD_ANALYZER);
|
||||||
final Parameter<NamedAnalyzer> searchAnalyzer
|
final Parameter<NamedAnalyzer> searchAnalyzer
|
||||||
= Parameter.analyzerParam("search_analyzer", true, m -> toType(m).searchAnalyzer, analyzer::getValue);
|
= Parameter.analyzerParam("search_analyzer", true, m -> toType(m).searchAnalyzer, analyzer::getValue);
|
||||||
final Parameter<Boolean> index = Parameter.boolParam("index", false, m -> toType(m).index, true);
|
final Parameter<Boolean> index = Parameter.boolParam("index", false, m -> toType(m).index, true);
|
||||||
|
@ -345,6 +345,12 @@ public class ParametrizedMapperTests extends ESSingleNodeTestCase {
|
||||||
TestMapper mapper = fromMapping(mapping);
|
TestMapper mapper = fromMapping(mapping);
|
||||||
assertEquals("wrapped value", mapper.wrapper.name);
|
assertEquals("wrapped value", mapper.wrapper.name);
|
||||||
assertEquals("{\"field\":" + mapping + "}", Strings.toString(mapper));
|
assertEquals("{\"field\":" + mapping + "}", Strings.toString(mapper));
|
||||||
|
|
||||||
|
String conflict = "{\"type\":\"test_mapper\",\"wrapper\":\"new value\",\"required\":\"value\"}";
|
||||||
|
TestMapper toMerge = fromMapping(conflict);
|
||||||
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> mapper.merge(toMerge));
|
||||||
|
assertEquals("Mapper for [field] conflicts with existing mapper:\n" +
|
||||||
|
"\tCannot update parameter [wrapper] from [wrapper_wrapped value] to [wrapper_new value]", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// test validator
|
// test validator
|
||||||
|
@ -383,6 +389,12 @@ public class ParametrizedMapperTests extends ESSingleNodeTestCase {
|
||||||
String badAnalyzer = "{\"type\":\"test_mapper\",\"analyzer\":\"wibble\",\"required\":\"value\"}";
|
String badAnalyzer = "{\"type\":\"test_mapper\",\"analyzer\":\"wibble\",\"required\":\"value\"}";
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> fromMapping(badAnalyzer));
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> fromMapping(badAnalyzer));
|
||||||
assertEquals("analyzer [wibble] has not been configured in mappings", e.getMessage());
|
assertEquals("analyzer [wibble] has not been configured in mappings", e.getMessage());
|
||||||
|
|
||||||
|
TestMapper original = mapper;
|
||||||
|
TestMapper toMerge = fromMapping(mapping);
|
||||||
|
e = expectThrows(IllegalArgumentException.class, () -> original.merge(toMerge));
|
||||||
|
assertEquals("Mapper for [field] conflicts with existing mapper:\n" +
|
||||||
|
"\tCannot update parameter [analyzer] from [default] to [_standard]", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDeprecatedParameters() {
|
public void testDeprecatedParameters() {
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
|
|
||||||
public void testExcludes() throws Exception {
|
public void testExcludes() throws Exception {
|
||||||
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
.startObject("_source").array("excludes", new String[]{"path1*"}).endObject()
|
.startObject("_source").array("excludes", "path1*").endObject()
|
||||||
.endObject().endObject());
|
.endObject().endObject());
|
||||||
|
|
||||||
DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser()
|
DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser()
|
||||||
|
@ -126,7 +126,7 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
.startObject("_source").field("enabled", false).endObject()
|
.startObject("_source").field("enabled", false).endObject()
|
||||||
.endObject().endObject());
|
.endObject().endObject());
|
||||||
assertConflicts(mapping1, mapping2, parser, "Cannot update enabled setting for [_source]");
|
assertConflicts(mapping1, mapping2, parser, "Cannot update parameter [enabled] from [true] to [false]");
|
||||||
|
|
||||||
// not changing is ok
|
// not changing is ok
|
||||||
String mapping3 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping3 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
|
@ -141,13 +141,13 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
String mapping1 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping1 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
.startObject("_source").array("includes", "foo.*").endObject()
|
.startObject("_source").array("includes", "foo.*").endObject()
|
||||||
.endObject().endObject());
|
.endObject().endObject());
|
||||||
assertConflicts(defaultMapping, mapping1, parser, "Cannot update includes setting for [_source]");
|
assertConflicts(defaultMapping, mapping1, parser, "Cannot update parameter [includes] from [[]] to [[foo.*]]");
|
||||||
assertConflicts(mapping1, defaultMapping, parser, "Cannot update includes setting for [_source]");
|
assertConflicts(mapping1, defaultMapping, parser, "Cannot update parameter [includes] from [[foo.*]] to [[]]");
|
||||||
|
|
||||||
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
.startObject("_source").array("includes", "foo.*", "bar.*").endObject()
|
.startObject("_source").array("includes", "foo.*", "bar.*").endObject()
|
||||||
.endObject().endObject());
|
.endObject().endObject());
|
||||||
assertConflicts(mapping1, mapping2, parser, "Cannot update includes setting for [_source]");
|
assertConflicts(mapping1, mapping2, parser, "Cannot update parameter [includes] from [[foo.*]] to [[foo.*, bar.*]]");
|
||||||
|
|
||||||
// not changing is ok
|
// not changing is ok
|
||||||
assertConflicts(mapping1, mapping1, parser);
|
assertConflicts(mapping1, mapping1, parser);
|
||||||
|
@ -159,13 +159,13 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
String mapping1 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping1 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
.startObject("_source").array("excludes", "foo.*").endObject()
|
.startObject("_source").array("excludes", "foo.*").endObject()
|
||||||
.endObject().endObject());
|
.endObject().endObject());
|
||||||
assertConflicts(defaultMapping, mapping1, parser, "Cannot update excludes setting for [_source]");
|
assertConflicts(defaultMapping, mapping1, parser, "Cannot update parameter [excludes] from [[]] to [[foo.*]]");
|
||||||
assertConflicts(mapping1, defaultMapping, parser, "Cannot update excludes setting for [_source]");
|
assertConflicts(mapping1, defaultMapping, parser, "Cannot update parameter [excludes] from [[foo.*]] to [[]]");
|
||||||
|
|
||||||
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
.startObject("_source").array("excludes", "foo.*", "bar.*").endObject()
|
.startObject("_source").array("excludes", "foo.*", "bar.*").endObject()
|
||||||
.endObject().endObject());
|
.endObject().endObject());
|
||||||
assertConflicts(mapping1, mapping2, parser, "Cannot update excludes setting for [_source]");
|
assertConflicts(mapping1, mapping2, parser, "Cannot update parameter [excludes]");
|
||||||
|
|
||||||
// not changing is ok
|
// not changing is ok
|
||||||
assertConflicts(mapping1, mapping1, parser);
|
assertConflicts(mapping1, mapping1, parser);
|
||||||
|
|
|
@ -30,10 +30,8 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.index.IndexSettings;
|
import org.elasticsearch.index.IndexSettings;
|
||||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||||
import org.elasticsearch.index.fielddata.plain.AbstractLeafOrdinalsFieldData;
|
import org.elasticsearch.index.fielddata.plain.AbstractLeafOrdinalsFieldData;
|
||||||
import org.elasticsearch.index.mapper.ContentPath;
|
|
||||||
import org.elasticsearch.index.mapper.IndexFieldMapper;
|
import org.elasticsearch.index.mapper.IndexFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
import org.elasticsearch.index.mapper.TextFieldMapper;
|
import org.elasticsearch.index.mapper.TextFieldMapper;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
@ -117,8 +115,7 @@ public class QueryShardContextTests extends ESTestCase {
|
||||||
final String clusterAlias = randomBoolean() ? null : "remote_cluster";
|
final String clusterAlias = randomBoolean() ? null : "remote_cluster";
|
||||||
QueryShardContext context = createQueryShardContext(IndexMetadata.INDEX_UUID_NA_VALUE, clusterAlias);
|
QueryShardContext context = createQueryShardContext(IndexMetadata.INDEX_UUID_NA_VALUE, clusterAlias);
|
||||||
|
|
||||||
Mapper.BuilderContext ctx = new Mapper.BuilderContext(context.getIndexSettings().getSettings(), new ContentPath());
|
IndexFieldMapper mapper = new IndexFieldMapper();
|
||||||
IndexFieldMapper mapper = new IndexFieldMapper.Builder().build(ctx);
|
|
||||||
|
|
||||||
IndexFieldData<?> forField = context.getForField(mapper.fieldType());
|
IndexFieldData<?> forField = context.getForField(mapper.fieldType());
|
||||||
String expected = clusterAlias == null ? context.getIndexSettings().getIndexMetadata().getIndex().getName()
|
String expected = clusterAlias == null ? context.getIndexSettings().getIndexMetadata().getIndex().getName()
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
|
||||||
"enabled=true"))),
|
"enabled=true"))),
|
||||||
MapperService.MergeReason.MAPPING_UPDATE);
|
MapperService.MergeReason.MAPPING_UPDATE);
|
||||||
}
|
}
|
||||||
assertWarnings(FieldNamesFieldMapper.TypeParser.ENABLED_DEPRECATION_MESSAGE.replace("{}", context.index().getName()));
|
assertWarnings(FieldNamesFieldMapper.ENABLED_DEPRECATION_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFromJson() throws IOException {
|
public void testFromJson() throws IOException {
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.IdFieldMapper;
|
import org.elasticsearch.index.mapper.IdFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.IgnoredFieldMapper;
|
import org.elasticsearch.index.mapper.IgnoredFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.IndexFieldMapper;
|
import org.elasticsearch.index.mapper.IndexFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
import org.elasticsearch.index.mapper.Mapper;
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||||
|
@ -63,17 +62,7 @@ public class IndicesModuleTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FakeMetadataMapperParser implements MetadataFieldMapper.TypeParser {
|
private static final MetadataFieldMapper.TypeParser PARSER = new MetadataFieldMapper.ConfigurableTypeParser(c -> null, c -> null);
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node, ParserContext parserContext)
|
|
||||||
throws MapperParsingException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext context) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<MapperPlugin> fakePlugins = Arrays.asList(new MapperPlugin() {
|
private final List<MapperPlugin> fakePlugins = Arrays.asList(new MapperPlugin() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,7 +71,7 @@ public class IndicesModuleTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap("fake-metadata-mapper", new FakeMetadataMapperParser());
|
return Collections.singletonMap("fake-metadata-mapper", PARSER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -180,7 +169,7 @@ public class IndicesModuleTests extends ESTestCase {
|
||||||
List<MapperPlugin> plugins = Arrays.asList(new MapperPlugin() {
|
List<MapperPlugin> plugins = Arrays.asList(new MapperPlugin() {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap(IdFieldMapper.NAME, new FakeMetadataMapperParser());
|
return Collections.singletonMap(IdFieldMapper.NAME, PARSER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
|
@ -192,7 +181,7 @@ public class IndicesModuleTests extends ESTestCase {
|
||||||
MapperPlugin plugin = new MapperPlugin() {
|
MapperPlugin plugin = new MapperPlugin() {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap("foo", new FakeMetadataMapperParser());
|
return Collections.singletonMap("foo", PARSER);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
List<MapperPlugin> plugins = Arrays.asList(plugin, plugin);
|
List<MapperPlugin> plugins = Arrays.asList(plugin, plugin);
|
||||||
|
@ -205,7 +194,7 @@ public class IndicesModuleTests extends ESTestCase {
|
||||||
List<MapperPlugin> plugins = Arrays.asList(new MapperPlugin() {
|
List<MapperPlugin> plugins = Arrays.asList(new MapperPlugin() {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap(FieldNamesFieldMapper.NAME, new FakeMetadataMapperParser());
|
return Collections.singletonMap(FieldNamesFieldMapper.NAME, PARSER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class DataStreamsPlugin extends Plugin implements ActionPlugin, MapperPlu
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
|
||||||
return Collections.singletonMap(DataStreamTimestampFieldMapper.NAME, new DataStreamTimestampFieldMapper.TypeParser());
|
return Collections.singletonMap(DataStreamTimestampFieldMapper.NAME, DataStreamTimestampFieldMapper.PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,23 +6,20 @@
|
||||||
|
|
||||||
package org.elasticsearch.xpack.datastreams.mapper;
|
package org.elasticsearch.xpack.datastreams.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.document.FieldType;
|
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
|
||||||
import org.elasticsearch.index.mapper.DateFieldMapper;
|
import org.elasticsearch.index.mapper.DateFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappingLookup;
|
import org.elasticsearch.index.mapper.MappingLookup;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
import org.elasticsearch.index.mapper.Mapper;
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
|
||||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||||
|
import org.elasticsearch.index.mapper.ParametrizedFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
import org.elasticsearch.index.mapper.TextSearchInfo;
|
import org.elasticsearch.index.mapper.TextSearchInfo;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
@ -31,10 +28,8 @@ import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||||
|
|
||||||
|
@ -43,16 +38,6 @@ public class DataStreamTimestampFieldMapper extends MetadataFieldMapper {
|
||||||
public static final String NAME = "_data_stream_timestamp";
|
public static final String NAME = "_data_stream_timestamp";
|
||||||
private static final String DEFAULT_PATH = "@timestamp";
|
private static final String DEFAULT_PATH = "@timestamp";
|
||||||
|
|
||||||
public static class Defaults {
|
|
||||||
|
|
||||||
public static final FieldType TIMESTAMP_FIELD_TYPE = new FieldType();
|
|
||||||
|
|
||||||
static {
|
|
||||||
TIMESTAMP_FIELD_TYPE.setIndexOptions(IndexOptions.NONE);
|
|
||||||
TIMESTAMP_FIELD_TYPE.freeze();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For now the field shouldn't be useable in searches.
|
// For now the field shouldn't be useable in searches.
|
||||||
// In the future it should act as an alias to the actual data stream timestamp field.
|
// In the future it should act as an alias to the actual data stream timestamp field.
|
||||||
public static final class TimestampFieldType extends MappedFieldType {
|
public static final class TimestampFieldType extends MappedFieldType {
|
||||||
|
@ -78,58 +63,47 @@ public class DataStreamTimestampFieldMapper extends MetadataFieldMapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends MetadataFieldMapper.Builder<Builder> {
|
private static DataStreamTimestampFieldMapper toType(FieldMapper in) {
|
||||||
|
return (DataStreamTimestampFieldMapper) in;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean enabled;
|
public static class Builder extends MetadataFieldMapper.Builder {
|
||||||
|
|
||||||
|
private final Parameter<Boolean> enabled = Parameter.boolParam("enabled", false, m -> toType(m).enabled, false);
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
super(NAME, Defaults.TIMESTAMP_FIELD_TYPE);
|
super(NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
@Override
|
||||||
this.enabled = enabled;
|
protected List<Parameter<?>> getParameters() {
|
||||||
|
return Collections.singletonList(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetadataFieldMapper build(BuilderContext context) {
|
public MetadataFieldMapper build(BuilderContext context) {
|
||||||
return new DataStreamTimestampFieldMapper(fieldType, new TimestampFieldType(), enabled);
|
return new DataStreamTimestampFieldMapper(new TimestampFieldType(), enabled.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeParser implements MetadataFieldMapper.TypeParser {
|
public static final TypeParser PARSER = new ConfigurableTypeParser(
|
||||||
|
c -> new DataStreamTimestampFieldMapper(new TimestampFieldType(), false),
|
||||||
|
c -> new Builder()
|
||||||
|
);
|
||||||
|
|
||||||
@Override
|
private final String path = DEFAULT_PATH;
|
||||||
public MetadataFieldMapper.Builder<?> parse(String name, Map<String, Object> node, ParserContext parserContext)
|
|
||||||
throws MapperParsingException {
|
|
||||||
Builder builder = new Builder();
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String fieldName = entry.getKey();
|
|
||||||
Object fieldNode = entry.getValue();
|
|
||||||
if (fieldName.equals("enabled")) {
|
|
||||||
builder.setEnabled(XContentMapValues.nodeBooleanValue(fieldNode, name + ".enabled"));
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext parserContext) {
|
|
||||||
return new DataStreamTimestampFieldMapper(Defaults.TIMESTAMP_FIELD_TYPE, new TimestampFieldType(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String path;
|
|
||||||
private final boolean enabled;
|
private final boolean enabled;
|
||||||
|
|
||||||
private DataStreamTimestampFieldMapper(FieldType fieldType, MappedFieldType mappedFieldType, boolean enabled) {
|
private DataStreamTimestampFieldMapper(MappedFieldType mappedFieldType, boolean enabled) {
|
||||||
super(fieldType, mappedFieldType);
|
super(mappedFieldType);
|
||||||
this.path = DEFAULT_PATH;
|
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
|
return new Builder().init(this);
|
||||||
|
}
|
||||||
|
|
||||||
public void doValidate(MappingLookup lookup) {
|
public void doValidate(MappingLookup lookup) {
|
||||||
if (enabled == false) {
|
if (enabled == false) {
|
||||||
// not configured, so skip the validation
|
// not configured, so skip the validation
|
||||||
|
@ -227,37 +201,8 @@ public class DataStreamTimestampFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
||||||
if (enabled == false) {
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.startObject(simpleName());
|
|
||||||
builder.field("enabled", enabled);
|
|
||||||
return builder.endObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean indexedByDefault() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean docValuesByDefault() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
|
||||||
DataStreamTimestampFieldMapper otherTimestampFieldMapper = (DataStreamTimestampFieldMapper) other;
|
|
||||||
if (Objects.equals(enabled, otherTimestampFieldMapper.enabled) == false) {
|
|
||||||
conflicts.add("cannot update enabled setting for [_data_stream_timestamp]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,12 +287,12 @@ public class DataStreamTimestampFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
"{\"type\":{\"_data_stream_timestamp\":{\"enabled\":false}, \"properties\": {\"@timestamp\": {\"type\": \"date\"}}}}}";
|
"{\"type\":{\"_data_stream_timestamp\":{\"enabled\":false}, \"properties\": {\"@timestamp\": {\"type\": \"date\"}}}}}";
|
||||||
String mapping2 = "{\"type\":{\"_data_stream_timestamp\":{\"enabled\":true}, \"properties\": {\"@timestamp2\": "
|
String mapping2 = "{\"type\":{\"_data_stream_timestamp\":{\"enabled\":true}, \"properties\": {\"@timestamp2\": "
|
||||||
+ "{\"type\": \"date\"},\"@timestamp\": {\"type\": \"date\"}}}})";
|
+ "{\"type\": \"date\"},\"@timestamp\": {\"type\": \"date\"}}}})";
|
||||||
assertConflicts(mapping1, mapping2, parser, "cannot update enabled setting for [_data_stream_timestamp]");
|
assertConflicts(mapping1, mapping2, parser, "Mapper for [_data_stream_timestamp]", "[enabled] from [false] to [true]");
|
||||||
|
|
||||||
mapping1 = "{\"type\":{\"properties\":{\"@timestamp\": {\"type\": \"date\"}}}}}";
|
mapping1 = "{\"type\":{\"properties\":{\"@timestamp\": {\"type\": \"date\"}}}}}";
|
||||||
mapping2 = "{\"type\":{\"_data_stream_timestamp\":{\"enabled\":true}, \"properties\": "
|
mapping2 = "{\"type\":{\"_data_stream_timestamp\":{\"enabled\":true}, \"properties\": "
|
||||||
+ "{\"@timestamp2\": {\"type\": \"date\"},\"@timestamp\": {\"type\": \"date\"}}}})";
|
+ "{\"@timestamp2\": {\"type\": \"date\"},\"@timestamp\": {\"type\": \"date\"}}}})";
|
||||||
assertConflicts(mapping1, mapping2, parser, "cannot update enabled setting for [_data_stream_timestamp]");
|
assertConflicts(mapping1, mapping2, parser, "Mapper for [_data_stream_timestamp]", "[enabled] from [false] to [true]");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue