For runtime fields, we will want to do all search-time interaction with a field definition via a MappedFieldType, rather than a FieldMapper, to avoid interfering with the logic of document parsing. Currently, fetching values for runtime scripts and for building top hits responses need to call a method on FieldMapper. This commit moves this method to MappedFieldType, incidentally simplifying the current call sites and freeing us up to implement runtime fields as pure MappedFieldType objects.
This commit is contained in:
parent
1c136bb7fc
commit
01950bc80f
|
@ -113,6 +113,19 @@ public class RankFeatureFieldMapper extends ParametrizedFieldMapper {
|
||||||
throw new IllegalArgumentException("[rank_feature] fields do not support sorting, scripting or aggregating");
|
throw new IllegalArgumentException("[rank_feature] fields do not support sorting, scripting or aggregating");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Float parseSourceValue(Object value) {
|
||||||
|
return objectToFloat(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
throw new IllegalArgumentException("Queries on [rank_feature] fields are not supported");
|
throw new IllegalArgumentException("Queries on [rank_feature] fields are not supported");
|
||||||
|
@ -162,7 +175,7 @@ public class RankFeatureFieldMapper extends ParametrizedFieldMapper {
|
||||||
context.doc().addWithKey(name(), new FeatureField("_feature", name(), value));
|
context.doc().addWithKey(name(), new FeatureField("_feature", name(), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Float objectToFloat(Object value) {
|
private static Float objectToFloat(Object value) {
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
return ((Number) value).floatValue();
|
return ((Number) value).floatValue();
|
||||||
} else {
|
} else {
|
||||||
|
@ -170,19 +183,6 @@ public class RankFeatureFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Float parseSourceValue(Object value) {
|
|
||||||
return objectToFloat(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -50,6 +51,11 @@ public class RankFeatureMetaFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query existsQuery(QueryShardContext context) {
|
public Query existsQuery(QueryShardContext context) {
|
||||||
throw new UnsupportedOperationException("Cannot run exists query on [_feature]");
|
throw new UnsupportedOperationException("Cannot run exists query on [_feature]");
|
||||||
|
|
|
@ -88,6 +88,19 @@ public class RankFeaturesFieldMapper extends ParametrizedFieldMapper {
|
||||||
throw new IllegalArgumentException("[rank_features] fields do not support sorting, scripting or aggregating");
|
throw new IllegalArgumentException("[rank_features] fields do not support sorting, scripting or aggregating");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
throw new IllegalArgumentException("Queries on [rank_features] fields are not supported");
|
throw new IllegalArgumentException("Queries on [rank_features] fields are not supported");
|
||||||
|
@ -152,19 +165,6 @@ public class RankFeaturesFieldMapper extends ParametrizedFieldMapper {
|
||||||
throw new AssertionError("parse is implemented directly");
|
throw new AssertionError("parse is implemented directly");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class ScaledFloatFieldMapper extends ParametrizedFieldMapper {
|
||||||
@Override
|
@Override
|
||||||
public ScaledFloatFieldMapper build(BuilderContext context) {
|
public ScaledFloatFieldMapper build(BuilderContext context) {
|
||||||
ScaledFloatFieldType type = new ScaledFloatFieldType(buildFullName(context), indexed.getValue(), stored.getValue(),
|
ScaledFloatFieldType type = new ScaledFloatFieldType(buildFullName(context), indexed.getValue(), stored.getValue(),
|
||||||
hasDocValues.getValue(), meta.getValue(), scalingFactor.getValue());
|
hasDocValues.getValue(), meta.getValue(), scalingFactor.getValue(), nullValue.getValue());
|
||||||
return new ScaledFloatFieldMapper(name, type, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
return new ScaledFloatFieldMapper(name, type, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,15 +134,17 @@ public class ScaledFloatFieldMapper extends ParametrizedFieldMapper {
|
||||||
public static final class ScaledFloatFieldType extends SimpleMappedFieldType {
|
public static final class ScaledFloatFieldType extends SimpleMappedFieldType {
|
||||||
|
|
||||||
private final double scalingFactor;
|
private final double scalingFactor;
|
||||||
|
private final Double nullValue;
|
||||||
|
|
||||||
public ScaledFloatFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
|
public ScaledFloatFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
|
||||||
Map<String, String> meta, double scalingFactor) {
|
Map<String, String> meta, double scalingFactor, Double nullValue) {
|
||||||
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
this.scalingFactor = scalingFactor;
|
this.scalingFactor = scalingFactor;
|
||||||
|
this.nullValue = nullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScaledFloatFieldType(String name, double scalingFactor) {
|
public ScaledFloatFieldType(String name, double scalingFactor) {
|
||||||
this(name, true, false, true, Collections.emptyMap(), scalingFactor);
|
this(name, true, false, true, Collections.emptyMap(), scalingFactor, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getScalingFactor() {
|
public double getScalingFactor() {
|
||||||
|
@ -218,6 +220,30 @@ public class ScaledFloatFieldMapper extends ParametrizedFieldMapper {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Double parseSourceValue(Object value) {
|
||||||
|
double doubleValue;
|
||||||
|
if (value.equals("")) {
|
||||||
|
if (nullValue == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
doubleValue = nullValue;
|
||||||
|
} else {
|
||||||
|
doubleValue = objectToDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
double scalingFactor = getScalingFactor();
|
||||||
|
return Math.round(doubleValue * scalingFactor) / scalingFactor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object valueForDisplay(Object value) {
|
public Object valueForDisplay(Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -394,31 +420,6 @@ public class ScaledFloatFieldMapper extends ParametrizedFieldMapper {
|
||||||
return doubleValue;
|
return doubleValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Double parseSourceValue(Object value) {
|
|
||||||
double doubleValue;
|
|
||||||
if (value.equals("")) {
|
|
||||||
if (nullValue == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
doubleValue = nullValue;
|
|
||||||
} else {
|
|
||||||
doubleValue = objectToDouble(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
double scalingFactor = fieldType().getScalingFactor();
|
|
||||||
return Math.round(doubleValue * scalingFactor) / scalingFactor;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static class ScaledFloatIndexFieldData extends IndexNumericFieldData {
|
private static class ScaledFloatIndexFieldData extends IndexNumericFieldData {
|
||||||
|
|
||||||
private final IndexNumericFieldData scaledFieldData;
|
private final IndexNumericFieldData scaledFieldData;
|
||||||
|
|
|
@ -263,6 +263,11 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
|
||||||
return shingleFields[Math.min(indexFromShingleSize, shingleFields.length - 1)];
|
return shingleFields[Math.min(indexFromShingleSize, shingleFields.length - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, QueryShardContext context) {
|
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, QueryShardContext context) {
|
||||||
if (prefixField == null || prefixField.termLengthWithinBounds(value.length()) == false) {
|
if (prefixField == null || prefixField.termLengthWithinBounds(value.length()) == false) {
|
||||||
|
@ -369,6 +374,11 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return "prefix";
|
return "prefix";
|
||||||
|
@ -405,11 +415,6 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
||||||
|
|
||||||
|
@ -451,11 +456,6 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return "shingle";
|
return "shingle";
|
||||||
|
@ -478,6 +478,11 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
|
||||||
this.prefixFieldType = prefixFieldType;
|
this.prefixFieldType = prefixFieldType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
@ -573,11 +578,6 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.TokenStream;
|
import org.apache.lucene.analysis.TokenStream;
|
||||||
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
|
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -79,6 +78,8 @@ public class TokenCountFieldMapper extends ParametrizedFieldMapper {
|
||||||
index.getValue(),
|
index.getValue(),
|
||||||
store.getValue(),
|
store.getValue(),
|
||||||
hasDocValues.getValue(),
|
hasDocValues.getValue(),
|
||||||
|
false,
|
||||||
|
nullValue.getValue(),
|
||||||
meta.getValue());
|
meta.getValue());
|
||||||
return new TokenCountFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
return new TokenCountFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
||||||
}
|
}
|
||||||
|
@ -129,20 +130,6 @@ public class TokenCountFieldMapper extends ParametrizedFieldMapper {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected String parseSourceValue(Object value) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count position increments in a token stream. Package private for testing.
|
* Count position increments in a token stream. Package private for testing.
|
||||||
* @param analyzer analyzer to create token stream
|
* @param analyzer analyzer to create token stream
|
||||||
|
|
|
@ -25,11 +25,8 @@ import org.apache.lucene.document.FeatureField;
|
||||||
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.apache.lucene.search.TermQuery;
|
import org.apache.lucene.search.TermQuery;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
import org.elasticsearch.common.collect.List;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
|
||||||
|
@ -144,13 +141,4 @@ public class RankFeatureFieldMapperTests extends MapperTestCase {
|
||||||
assertEquals("[rank_feature] fields do not support indexing multiple values for the same field [foo.field] in the same document",
|
assertEquals("[rank_feature] fields do not support indexing multiple values for the same field [foo.field] in the same document",
|
||||||
e.getCause().getMessage());
|
e.getCause().getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
RankFeatureFieldMapper mapper = new RankFeatureFieldMapper.Builder("field").build(context);
|
|
||||||
|
|
||||||
assertEquals(List.of(3.14f), fetchSourceValue(mapper, 3.14));
|
|
||||||
assertEquals(List.of(42.9f), fetchSourceValue(mapper, "42.9"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
public class RankFeatureFieldTypeTests extends FieldTypeTestCase {
|
public class RankFeatureFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
@ -27,4 +32,13 @@ public class RankFeatureFieldTypeTests extends FieldTypeTestCase {
|
||||||
MappedFieldType fieldType = new RankFeatureFieldMapper.RankFeatureFieldType("field", Collections.emptyMap(), true);
|
MappedFieldType fieldType = new RankFeatureFieldMapper.RankFeatureFieldType("field", Collections.emptyMap(), true);
|
||||||
assertFalse(fieldType.isAggregatable());
|
assertFalse(fieldType.isAggregatable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
MappedFieldType mapper = new RankFeatureFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
|
||||||
|
assertEquals(Collections.singletonList(3.14f), fetchSourceValue(mapper, 3.14));
|
||||||
|
assertEquals(Collections.singletonList(42.9f), fetchSourceValue(mapper, "42.9"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,8 @@ package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
@ -285,22 +282,4 @@ public class ScaledFloatFieldMapperTests extends MapperTestCase {
|
||||||
containsString("Failed to parse mapping [_doc]: Field [scaling_factor] is required"));
|
containsString("Failed to parse mapping [_doc]: Field [scaling_factor] is required"));
|
||||||
assertWarnings("Parameter [index_options] has no effect on type [scaled_float] and will be removed in future");
|
assertWarnings("Parameter [index_options] has no effect on type [scaled_float] and will be removed in future");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
ScaledFloatFieldMapper mapper = new ScaledFloatFieldMapper.Builder("field", false, false)
|
|
||||||
.scalingFactor(100)
|
|
||||||
.build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(3.14), fetchSourceValue(mapper, 3.1415926));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(3.14), fetchSourceValue(mapper, "3.1415"));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(), fetchSourceValue(mapper, ""));
|
|
||||||
|
|
||||||
ScaledFloatFieldMapper nullValueMapper = new ScaledFloatFieldMapper.Builder("field", false, false)
|
|
||||||
.scalingFactor(100)
|
|
||||||
.nullValue(2.71)
|
|
||||||
.build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(2.71), fetchSourceValue(nullValueMapper, ""));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ import org.apache.lucene.index.IndexWriterConfig;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.core.internal.io.IOUtils;
|
import org.elasticsearch.core.internal.io.IOUtils;
|
||||||
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
|
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
|
||||||
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
|
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
|
||||||
|
@ -65,7 +68,7 @@ public class ScaledFloatFieldTypeTests extends FieldTypeTestCase {
|
||||||
// this test checks that searching scaled floats yields the same results as
|
// this test checks that searching scaled floats yields the same results as
|
||||||
// searching doubles that are rounded to the closest half float
|
// searching doubles that are rounded to the closest half float
|
||||||
ScaledFloatFieldMapper.ScaledFloatFieldType ft = new ScaledFloatFieldMapper.ScaledFloatFieldType(
|
ScaledFloatFieldMapper.ScaledFloatFieldType ft = new ScaledFloatFieldMapper.ScaledFloatFieldType(
|
||||||
"scaled_float", true, false, false, Collections.emptyMap(), 0.1 + randomDouble() * 100);
|
"scaled_float", true, false, false, Collections.emptyMap(), 0.1 + randomDouble() * 100, null);
|
||||||
Directory dir = newDirectory();
|
Directory dir = newDirectory();
|
||||||
IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(null));
|
IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(null));
|
||||||
final int numDocs = 1000;
|
final int numDocs = 1000;
|
||||||
|
@ -175,4 +178,24 @@ public class ScaledFloatFieldTypeTests extends FieldTypeTestCase {
|
||||||
}
|
}
|
||||||
IOUtils.close(w, dir);
|
IOUtils.close(w, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new ScaledFloatFieldMapper.Builder("field", false, false)
|
||||||
|
.scalingFactor(100)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList(3.14), fetchSourceValue(mapper, 3.1415926));
|
||||||
|
assertEquals(Collections.singletonList(3.14), fetchSourceValue(mapper, "3.1415"));
|
||||||
|
assertEquals(Collections.emptyList(), fetchSourceValue(mapper, ""));
|
||||||
|
|
||||||
|
MappedFieldType nullValueMapper = new ScaledFloatFieldMapper.Builder("field", false, false)
|
||||||
|
.scalingFactor(100)
|
||||||
|
.nullValue(2.71)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList(2.71), fetchSourceValue(nullValueMapper, ""));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,11 @@ public class MetaJoinFieldMapper extends FieldMapper {
|
||||||
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for metadata field [" + typeName() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object valueForDisplay(Object value) {
|
public Object valueForDisplay(Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -139,11 +144,6 @@ public class MetaJoinFieldMapper extends FieldMapper {
|
||||||
throw new IllegalStateException("Should never be called");
|
throw new IllegalStateException("Should never be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException("Cannot fetch values for metadata field [" + typeName() + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -113,6 +113,11 @@ public final class ParentIdFieldMapper extends FieldMapper {
|
||||||
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object valueForDisplay(Object value) {
|
public Object valueForDisplay(Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -182,11 +187,6 @@ public final class ParentIdFieldMapper extends FieldMapper {
|
||||||
context.doc().add(new SortedDocValuesField(fieldType().name(), binaryValue));
|
context.doc().add(new SortedDocValuesField(fieldType().name(), binaryValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
||||||
ParentIdFieldMapper parentMergeWith = (ParentIdFieldMapper) other;
|
ParentIdFieldMapper parentMergeWith = (ParentIdFieldMapper) other;
|
||||||
|
|
|
@ -222,6 +222,19 @@ public final class ParentJoinFieldMapper extends FieldMapper {
|
||||||
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object valueForDisplay(Object value) {
|
public Object valueForDisplay(Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -343,19 +356,6 @@ public final class ParentJoinFieldMapper extends FieldMapper {
|
||||||
throw new UnsupportedOperationException("parsing is implemented in parse(), this method should NEVER be called");
|
throw new UnsupportedOperationException("parsing is implemented in parse(), this method should NEVER be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void parse(ParseContext context) throws IOException {
|
public void parse(ParseContext context) throws IOException {
|
||||||
context.path().add(simpleName());
|
context.path().add(simpleName());
|
||||||
|
|
|
@ -224,6 +224,19 @@ public class PercolatorFieldMapper extends ParametrizedFieldMapper {
|
||||||
throw new QueryShardException(context, "Percolator fields are not searchable directly, use a percolate query instead");
|
throw new QueryShardException(context, "Percolator fields are not searchable directly, use a percolate query instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Query percolateQuery(String name, PercolateQuery.QueryStore queryStore, List<BytesReference> documents,
|
Query percolateQuery(String name, PercolateQuery.QueryStore queryStore, List<BytesReference> documents,
|
||||||
IndexSearcher searcher, boolean excludeNestedDocuments, Version indexVersion) throws IOException {
|
IndexSearcher searcher, boolean excludeNestedDocuments, Version indexVersion) throws IOException {
|
||||||
IndexReader indexReader = searcher.getIndexReader();
|
IndexReader indexReader = searcher.getIndexReader();
|
||||||
|
@ -373,19 +386,6 @@ public class PercolatorFieldMapper extends ParametrizedFieldMapper {
|
||||||
processQuery(query, context);
|
processQuery(query, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void createQueryBuilderField(Version indexVersion, BinaryFieldMapper qbField,
|
static void createQueryBuilderField(Version indexVersion, BinaryFieldMapper qbField,
|
||||||
QueryBuilder queryBuilder, ParseContext context) throws IOException {
|
QueryBuilder queryBuilder, ParseContext context) throws IOException {
|
||||||
if (indexVersion.onOrAfter(Version.V_6_0_0_beta2)) {
|
if (indexVersion.onOrAfter(Version.V_6_0_0_beta2)) {
|
||||||
|
|
|
@ -68,22 +68,29 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
|
||||||
FIELD_TYPE.freeze();
|
FIELD_TYPE.freeze();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String NULL_VALUE = null;
|
|
||||||
public static final int IGNORE_ABOVE = Integer.MAX_VALUE;
|
public static final int IGNORE_ABOVE = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class CollationFieldType extends StringFieldType {
|
public static final class CollationFieldType extends StringFieldType {
|
||||||
private final Collator collator;
|
private final Collator collator;
|
||||||
|
private final String nullValue;
|
||||||
|
private final int ignoreAbove;
|
||||||
|
|
||||||
public CollationFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
public CollationFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
||||||
Collator collator, Map<String, String> meta) {
|
Collator collator, String nullValue, int ignoreAbove, Map<String, String> meta) {
|
||||||
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
||||||
this.collator = collator;
|
this.collator = collator;
|
||||||
|
this.nullValue = nullValue;
|
||||||
|
this.ignoreAbove = ignoreAbove;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CollationFieldType(String name, boolean searchable, Collator collator) {
|
||||||
|
this(name, searchable, false, true, collator, null, Integer.MAX_VALUE, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CollationFieldType(String name, Collator collator) {
|
public CollationFieldType(String name, Collator collator) {
|
||||||
this(name, true, false, true, collator, Collections.emptyMap());
|
this(name, true, false, true, collator, null, Integer.MAX_VALUE, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,8 +98,22 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collator collator() {
|
@Override
|
||||||
return collator;
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
protected String parseSourceValue(Object value) {
|
||||||
|
String keywordValue = value.toString();
|
||||||
|
if (keywordValue.length() > ignoreAbove) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return keywordValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -429,8 +450,9 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
|
||||||
@Override
|
@Override
|
||||||
public ICUCollationKeywordFieldMapper build(BuilderContext context) {
|
public ICUCollationKeywordFieldMapper build(BuilderContext context) {
|
||||||
final Collator collator = buildCollator();
|
final Collator collator = buildCollator();
|
||||||
CollationFieldType ft = new CollationFieldType(buildFullName(context), indexed, fieldType.stored(), hasDocValues,
|
CollationFieldType ft
|
||||||
collator, meta);
|
= new CollationFieldType(buildFullName(context), indexed, fieldType.stored(),
|
||||||
|
hasDocValues, collator, nullValue, ignoreAbove, meta);
|
||||||
return new ICUCollationKeywordFieldMapper(name, fieldType, ft,
|
return new ICUCollationKeywordFieldMapper(name, fieldType, ft,
|
||||||
multiFieldsBuilder.build(this, context), copyTo, rules, language, country, variant, strength, decomposition,
|
multiFieldsBuilder.build(this, context), copyTo, rules, language, country, variant, strength, decomposition,
|
||||||
alternate, caseLevel, caseFirst, numeric, variableTop, hiraganaQuaternaryMode, ignoreAbove, collator, nullValue);
|
alternate, caseLevel, caseFirst, numeric, variableTop, hiraganaQuaternaryMode, ignoreAbove, collator, nullValue);
|
||||||
|
@ -726,22 +748,4 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected String parseSourceValue(Object value) {
|
|
||||||
String keywordValue = value.toString();
|
|
||||||
if (keywordValue.length() > ignoreAbove) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return keywordValue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.elasticsearch.index.mapper.MappedFieldType.Relation;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CollationFieldTypeTests extends FieldTypeTestCase{
|
public class CollationFieldTypeTests extends FieldTypeTestCase{
|
||||||
|
@ -66,7 +65,7 @@ public class CollationFieldTypeTests extends FieldTypeTestCase{
|
||||||
|
|
||||||
assertEquals(new TermQuery(new Term("field", expected)), ft.termQuery("I WİLL USE TURKİSH CASING", null));
|
assertEquals(new TermQuery(new Term("field", expected)), ft.termQuery("I WİLL USE TURKİSH CASING", null));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new CollationFieldType("field", false, false, true, collator, Collections.emptyMap());
|
MappedFieldType unsearchable = new CollationFieldType("field", false, collator);
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.termQuery("bar", null));
|
() -> unsearchable.termQuery("bar", null));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -86,7 +85,7 @@ public class CollationFieldTypeTests extends FieldTypeTestCase{
|
||||||
assertEquals(new TermInSetQuery("field", terms),
|
assertEquals(new TermInSetQuery("field", terms),
|
||||||
ft.termsQuery(Arrays.asList("foo", "bar"), null));
|
ft.termsQuery(Arrays.asList("foo", "bar"), null));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new CollationFieldType("field", false, false, true, collator, Collections.emptyMap());
|
MappedFieldType unsearchable = new CollationFieldType("field", false, collator);
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.termsQuery(Arrays.asList("foo", "bar"), null));
|
() -> unsearchable.termsQuery(Arrays.asList("foo", "bar"), null));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -135,7 +134,7 @@ public class CollationFieldTypeTests extends FieldTypeTestCase{
|
||||||
assertEquals("[range] queries on [text] or [keyword] fields cannot be executed when " +
|
assertEquals("[range] queries on [text] or [keyword] fields cannot be executed when " +
|
||||||
"'search.allow_expensive_queries' is set to false.", ee.getMessage());
|
"'search.allow_expensive_queries' is set to false.", ee.getMessage());
|
||||||
|
|
||||||
MappedFieldType unsearchable = new CollationFieldType("field", false, false, true, DEFAULT_COLLATOR, Collections.emptyMap());
|
MappedFieldType unsearchable = new CollationFieldType("field", false, DEFAULT_COLLATOR);
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.rangeQuery("a", "b", false, false, null, null, null, MOCK_QSC));
|
() -> unsearchable.rangeQuery("a", "b", false, false, null, null, null, MOCK_QSC));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
|
|
@ -26,11 +26,8 @@ import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.index.IndexableFieldType;
|
import org.apache.lucene.index.IndexableFieldType;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
import org.elasticsearch.common.collect.List;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.plugin.analysis.icu.AnalysisICUPlugin;
|
import org.elasticsearch.plugin.analysis.icu.AnalysisICUPlugin;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
@ -120,7 +117,8 @@ public class ICUCollationKeywordFieldMapperTests extends FieldMapperTestCase2<IC
|
||||||
assertArrayEquals(new IndexableField[0], doc.rootDoc().getFields("field"));
|
assertArrayEquals(new IndexableField[0], doc.rootDoc().getFields("field"));
|
||||||
|
|
||||||
mapper = createDocumentMapper(fieldMapping(b -> b.field("type", FIELD_TYPE).field("null_value", "1234")));
|
mapper = createDocumentMapper(fieldMapping(b -> b.field("type", FIELD_TYPE).field("null_value", "1234")));
|
||||||
doc = mapper.parse(source(b -> {}));
|
doc = mapper.parse(source(b -> {
|
||||||
|
}));
|
||||||
|
|
||||||
IndexableField[] fields = doc.rootDoc().getFields("field");
|
IndexableField[] fields = doc.rootDoc().getFields("field");
|
||||||
assertEquals(0, fields.length);
|
assertEquals(0, fields.length);
|
||||||
|
@ -298,24 +296,4 @@ public class ICUCollationKeywordFieldMapperTests extends FieldMapperTestCase2<IC
|
||||||
assertEquals(0, fields.length);
|
assertEquals(0, fields.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
ICUCollationKeywordFieldMapper mapper = new ICUCollationKeywordFieldMapper.Builder("field").build(context);
|
|
||||||
assertEquals(List.of("42"), fetchSourceValue(mapper, 42L));
|
|
||||||
assertEquals(List.of("true"), fetchSourceValue(mapper, true));
|
|
||||||
|
|
||||||
ICUCollationKeywordFieldMapper ignoreAboveMapper = new ICUCollationKeywordFieldMapper.Builder("field")
|
|
||||||
.ignoreAbove(4)
|
|
||||||
.build(context);
|
|
||||||
assertEquals(List.of(), fetchSourceValue(ignoreAboveMapper, "value"));
|
|
||||||
assertEquals(List.of("42"), fetchSourceValue(ignoreAboveMapper, 42L));
|
|
||||||
assertEquals(List.of("true"), fetchSourceValue(ignoreAboveMapper, true));
|
|
||||||
|
|
||||||
ICUCollationKeywordFieldMapper nullValueMapper = new ICUCollationKeywordFieldMapper.Builder("field")
|
|
||||||
.nullValue("NULL")
|
|
||||||
.build(context);
|
|
||||||
assertEquals(List.of("NULL"), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class ICUCollationKeywordFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
ICUCollationKeywordFieldMapper mapper = new ICUCollationKeywordFieldMapper.Builder("field").build(context);
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(mapper.fieldType(), 42L));
|
||||||
|
assertEquals(Collections.singletonList("true"), fetchSourceValue(mapper.fieldType(), true));
|
||||||
|
|
||||||
|
ICUCollationKeywordFieldMapper ignoreAboveMapper = new ICUCollationKeywordFieldMapper.Builder("field")
|
||||||
|
.ignoreAbove(4)
|
||||||
|
.build(context);
|
||||||
|
assertEquals(Collections.emptyList(), fetchSourceValue(ignoreAboveMapper.fieldType(), "value"));
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(ignoreAboveMapper.fieldType(), 42L));
|
||||||
|
assertEquals(Collections.singletonList("true"), fetchSourceValue(ignoreAboveMapper.fieldType(), true));
|
||||||
|
|
||||||
|
ICUCollationKeywordFieldMapper nullValueMapper = new ICUCollationKeywordFieldMapper.Builder("field")
|
||||||
|
.nullValue("NULL")
|
||||||
|
.build(context);
|
||||||
|
assertEquals(Collections.singletonList("NULL"), fetchSourceValue(nullValueMapper.fieldType(), null));
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,12 +28,10 @@ import org.apache.lucene.index.PostingsEnum;
|
||||||
import org.apache.lucene.index.Terms;
|
import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.index.TermsEnum;
|
import org.apache.lucene.index.TermsEnum;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.action.bulk.BulkRequestBuilder;
|
import org.elasticsearch.action.bulk.BulkRequestBuilder;
|
||||||
import org.elasticsearch.action.index.IndexRequest;
|
import org.elasticsearch.action.index.IndexRequest;
|
||||||
import org.elasticsearch.action.termvectors.TermVectorsRequest;
|
import org.elasticsearch.action.termvectors.TermVectorsRequest;
|
||||||
import org.elasticsearch.action.termvectors.TermVectorsResponse;
|
import org.elasticsearch.action.termvectors.TermVectorsResponse;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.compress.CompressedXContent;
|
import org.elasticsearch.common.compress.CompressedXContent;
|
||||||
|
@ -46,11 +44,8 @@ import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.index.IndexService;
|
import org.elasticsearch.index.IndexService;
|
||||||
import org.elasticsearch.index.VersionType;
|
import org.elasticsearch.index.VersionType;
|
||||||
import org.elasticsearch.index.engine.Engine;
|
import org.elasticsearch.index.engine.Engine;
|
||||||
import org.elasticsearch.index.mapper.ContentPath;
|
|
||||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||||
import org.elasticsearch.index.mapper.DocumentMapperParser;
|
import org.elasticsearch.index.mapper.DocumentMapperParser;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
import org.elasticsearch.index.mapper.MapperService.MergeReason;
|
import org.elasticsearch.index.mapper.MapperService.MergeReason;
|
||||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||||
|
@ -76,7 +71,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.index.mapper.FieldMapperTestCase.fetchSourceValue;
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
@ -677,20 +671,4 @@ public class AnnotatedTextFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
);
|
);
|
||||||
assertThat(e.getMessage(), containsString("name cannot be empty string"));
|
assertThat(e.getMessage(), containsString("name cannot be empty string"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
FieldMapper fieldMapper = new AnnotatedTextFieldMapper.Builder("field")
|
|
||||||
.indexAnalyzer(indexService.getIndexAnalyzers().getDefaultIndexAnalyzer())
|
|
||||||
.searchAnalyzer(indexService.getIndexAnalyzers().getDefaultSearchAnalyzer())
|
|
||||||
.searchQuoteAnalyzer(indexService.getIndexAnalyzers().getDefaultSearchQuoteAnalyzer())
|
|
||||||
.build(context);
|
|
||||||
AnnotatedTextFieldMapper mapper = (AnnotatedTextFieldMapper) fieldMapper;
|
|
||||||
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("value"), fetchSourceValue(mapper, "value"));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("42"), fetchSourceValue(mapper, 42L));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("true"), fetchSourceValue(mapper, true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,10 @@ import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
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.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
import org.elasticsearch.index.mapper.SourceValueFetcher;
|
|
||||||
import org.elasticsearch.index.mapper.TextFieldMapper;
|
import org.elasticsearch.index.mapper.TextFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.ValueFetcher;
|
|
||||||
import org.elasticsearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText.AnnotationToken;
|
import org.elasticsearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText.AnnotationToken;
|
||||||
import org.elasticsearch.index.similarity.SimilarityProvider;
|
import org.elasticsearch.index.similarity.SimilarityProvider;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
@ -586,19 +582,6 @@ public class AnnotatedTextFieldMapper extends FieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -22,10 +22,16 @@ package org.elasticsearch.index.mapper.annotatedtext;
|
||||||
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||||
import org.apache.lucene.queries.intervals.Intervals;
|
import org.apache.lucene.queries.intervals.Intervals;
|
||||||
import org.apache.lucene.queries.intervals.IntervalsSource;
|
import org.apache.lucene.queries.intervals.IntervalsSource;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.index.analysis.AnalyzerScope;
|
import org.elasticsearch.index.analysis.AnalyzerScope;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
|
import org.elasticsearch.index.mapper.ContentPath;
|
||||||
import org.elasticsearch.index.mapper.FieldTypeTestCase;
|
import org.elasticsearch.index.mapper.FieldTypeTestCase;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
|
import org.elasticsearch.index.mapper.Mapper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -38,4 +44,20 @@ public class AnnotatedTextFieldTypeTests extends FieldTypeTestCase {
|
||||||
IntervalsSource source = ft.intervals("Donald Trump", 0, true, a, false);
|
IntervalsSource source = ft.intervals("Donald Trump", 0, true, a, false);
|
||||||
assertEquals(Intervals.phrase(Intervals.term("donald"), Intervals.term("trump")), source);
|
assertEquals(Intervals.phrase(Intervals.term("donald"), Intervals.term("trump")), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType fieldType = new AnnotatedTextFieldMapper.Builder("field")
|
||||||
|
.indexAnalyzer(Lucene.STANDARD_ANALYZER)
|
||||||
|
.searchAnalyzer(Lucene.STANDARD_ANALYZER)
|
||||||
|
.searchQuoteAnalyzer(Lucene.STANDARD_ANALYZER)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
|
||||||
|
assertEquals(Collections.singletonList("value"), fetchSourceValue(fieldType, "value"));
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(fieldType, 42L));
|
||||||
|
assertEquals(Collections.singletonList("true"), fetchSourceValue(fieldType, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,19 @@ public class Murmur3FieldMapper extends ParametrizedFieldMapper {
|
||||||
return new SortedNumericIndexFieldData.Builder(name(), NumericType.LONG);
|
return new SortedNumericIndexFieldData.Builder(name(), NumericType.LONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected String parseSourceValue(Object value) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
throw new QueryShardException(context, "Murmur3 fields are not searchable: [" + name() + "]");
|
throw new QueryShardException(context, "Murmur3 fields are not searchable: [" + name() + "]");
|
||||||
|
@ -148,17 +161,4 @@ public class Murmur3FieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected String parseSourceValue(Object value) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,22 +179,6 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
String geoFormat = format != null ? format : GeoJsonGeometryFormat.NAME;
|
|
||||||
|
|
||||||
AbstractGeometryFieldType<Parsed, Processed> mappedFieldType = fieldType();
|
|
||||||
Parser<Parsed> geometryParser = mappedFieldType.geometryParser();
|
|
||||||
Function<Object, Object> valueParser = value -> geometryParser.parseAndFormatObject(value, geoFormat);
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return valueParser.apply(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class TypeParser<T extends Builder> implements Mapper.TypeParser {
|
public abstract static class TypeParser<T extends Builder> implements Mapper.TypeParser {
|
||||||
protected abstract T newBuilder(String name, Map<String, Object> params);
|
protected abstract T newBuilder(String name, Map<String, Object> params);
|
||||||
|
|
||||||
|
@ -239,9 +223,12 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
||||||
|
|
||||||
protected Indexer<Parsed, Processed> geometryIndexer;
|
protected Indexer<Parsed, Processed> geometryIndexer;
|
||||||
protected Parser<Parsed> geometryParser;
|
protected Parser<Parsed> geometryParser;
|
||||||
|
protected final boolean parsesArrayValue;
|
||||||
|
|
||||||
protected AbstractGeometryFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
protected AbstractGeometryFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
|
||||||
|
boolean parsesArrayValue, Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
|
this.parsesArrayValue = parsesArrayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGeometryIndexer(Indexer<Parsed, Processed> geometryIndexer) {
|
public void setGeometryIndexer(Indexer<Parsed, Processed> geometryIndexer) {
|
||||||
|
@ -266,6 +253,20 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
||||||
"Geometry fields do not support exact searching, use dedicated geometry queries instead: ["
|
"Geometry fields do not support exact searching, use dedicated geometry queries instead: ["
|
||||||
+ name() + "]");
|
+ name() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
String geoFormat = format != null ? format : GeoJsonGeometryFormat.NAME;
|
||||||
|
|
||||||
|
Function<Object, Object> valueParser = value -> geometryParser.parseAndFormatObject(value, geoFormat);
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, parsesArrayValue) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return valueParser.apply(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Explicit<Boolean> ignoreMalformed;
|
protected Explicit<Boolean> ignoreMalformed;
|
||||||
|
|
|
@ -119,7 +119,7 @@ public abstract class AbstractPointGeometryFieldMapper<Parsed, Processed> extend
|
||||||
extends AbstractGeometryFieldType<Parsed, Processed> {
|
extends AbstractGeometryFieldType<Parsed, Processed> {
|
||||||
protected AbstractPointGeometryFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
|
protected AbstractPointGeometryFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
|
||||||
Map<String, String> meta) {
|
Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, meta);
|
super(name, indexed, stored, hasDocValues, true, meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,8 +158,8 @@ public abstract class AbstractShapeGeometryFieldMapper<Parsed, Processed> extend
|
||||||
protected Orientation orientation = Defaults.ORIENTATION.value();
|
protected Orientation orientation = Defaults.ORIENTATION.value();
|
||||||
|
|
||||||
protected AbstractShapeGeometryFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
protected AbstractShapeGeometryFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
||||||
Map<String, String> meta) {
|
boolean parsesArrayValue, Map<String, String> meta) {
|
||||||
super(name, isSearchable, isStored, hasDocValues, meta);
|
super(name, isSearchable, isStored, hasDocValues, parsesArrayValue, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Orientation orientation() { return this.orientation; }
|
public Orientation orientation() { return this.orientation; }
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.lucene.search.MatchNoDocsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.Explicit;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -85,6 +86,11 @@ public class AllFieldMapper extends MetadataFieldMapper {
|
||||||
super(NAME, false, false, false, TextSearchInfo.NONE, Collections.emptyMap());
|
super(NAME, false, false, false, TextSearchInfo.NONE, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -98,6 +98,19 @@ public class BinaryFieldMapper extends ParametrizedFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
|
public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
|
||||||
return DocValueFormat.BINARY;
|
return DocValueFormat.BINARY;
|
||||||
|
@ -180,19 +193,6 @@ public class BinaryFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
return new BinaryFieldMapper.Builder(simpleName()).init(this);
|
return new BinaryFieldMapper.Builder(simpleName()).init(this);
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class BooleanFieldMapper extends ParametrizedFieldMapper {
|
||||||
@Override
|
@Override
|
||||||
public BooleanFieldMapper build(BuilderContext context) {
|
public BooleanFieldMapper build(BuilderContext context) {
|
||||||
MappedFieldType ft = new BooleanFieldType(buildFullName(context), indexed.getValue(), stored.getValue(),
|
MappedFieldType ft = new BooleanFieldType(buildFullName(context), indexed.getValue(), stored.getValue(),
|
||||||
docValues.getValue(), meta.getValue());
|
docValues.getValue(), nullValue.getValue(), meta.getValue());
|
||||||
ft.setBoost(boost.getValue());
|
ft.setBoost(boost.getValue());
|
||||||
return new BooleanFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
return new BooleanFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
||||||
}
|
}
|
||||||
|
@ -108,13 +108,20 @@ public class BooleanFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
public static final class BooleanFieldType extends TermBasedFieldType {
|
public static final class BooleanFieldType extends TermBasedFieldType {
|
||||||
|
|
||||||
|
private final Boolean nullValue;
|
||||||
|
|
||||||
public BooleanFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
public BooleanFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
||||||
Map<String, String> meta) {
|
Boolean nullValue, Map<String, String> meta) {
|
||||||
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
|
this.nullValue = nullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanFieldType(String name) {
|
public BooleanFieldType(String name) {
|
||||||
this(name, true, false, true, Collections.emptyMap());
|
this(name, true, false, true, false, Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanFieldType(String name, boolean searchable) {
|
||||||
|
this(name, searchable, false, true, false, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -122,6 +129,25 @@ public class BooleanFieldMapper extends ParametrizedFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
protected Boolean parseSourceValue(Object value) {
|
||||||
|
if (value instanceof Boolean) {
|
||||||
|
return (Boolean) value;
|
||||||
|
} else {
|
||||||
|
String textValue = value.toString();
|
||||||
|
return Booleans.parseBoolean(textValue.toCharArray(), 0, textValue.length(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BytesRef indexedValueForSearch(Object value) {
|
public BytesRef indexedValueForSearch(Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -243,25 +269,6 @@ public class BooleanFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected Boolean parseSourceValue(Object value) {
|
|
||||||
if (value instanceof Boolean) {
|
|
||||||
return (Boolean) value;
|
|
||||||
} else {
|
|
||||||
String textValue = value.toString();
|
|
||||||
return Booleans.parseBoolean(textValue.toCharArray(), 0, textValue.length(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
return new Builder(simpleName()).init(this);
|
return new Builder(simpleName()).init(this);
|
||||||
|
|
|
@ -301,6 +301,24 @@ public class CompletionFieldMapper extends ParametrizedFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, true) {
|
||||||
|
@Override
|
||||||
|
protected List<?> parseSourceValue(Object value) {
|
||||||
|
if (value instanceof List) {
|
||||||
|
return (List<?>) value;
|
||||||
|
} else {
|
||||||
|
return Collections.singletonList(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int maxInputLength;
|
private final int maxInputLength;
|
||||||
|
@ -515,24 +533,6 @@ public class CompletionFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected List<?> parseSourceValue(Object value) {
|
|
||||||
if (value instanceof List) {
|
|
||||||
return (List<?>) value;
|
|
||||||
} else {
|
|
||||||
return org.elasticsearch.common.collect.List.of(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CompletionInputMetadata {
|
static class CompletionInputMetadata {
|
||||||
public final String input;
|
public final String input;
|
||||||
public final Map<String, Set<String>> contexts;
|
public final Map<String, Set<String>> contexts;
|
||||||
|
|
|
@ -251,7 +251,7 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
|
||||||
@Override
|
@Override
|
||||||
public DateFieldMapper build(BuilderContext context) {
|
public DateFieldMapper build(BuilderContext context) {
|
||||||
DateFieldType ft = new DateFieldType(buildFullName(context), index.getValue(), store.getValue(), docValues.getValue(),
|
DateFieldType ft = new DateFieldType(buildFullName(context), index.getValue(), store.getValue(), docValues.getValue(),
|
||||||
buildFormatter(), resolution, meta.getValue());
|
buildFormatter(), resolution, nullValue.getValue(), meta.getValue());
|
||||||
ft.setBoost(boost.getValue());
|
ft.setBoost(boost.getValue());
|
||||||
Long nullTimestamp = parseNullValue(ft);
|
Long nullTimestamp = parseNullValue(ft);
|
||||||
return new DateFieldMapper(name, ft, multiFieldsBuilder.build(this, context),
|
return new DateFieldMapper(name, ft, multiFieldsBuilder.build(this, context),
|
||||||
|
@ -273,25 +273,32 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
|
||||||
protected final DateFormatter dateTimeFormatter;
|
protected final DateFormatter dateTimeFormatter;
|
||||||
protected final DateMathParser dateMathParser;
|
protected final DateMathParser dateMathParser;
|
||||||
protected final Resolution resolution;
|
protected final Resolution resolution;
|
||||||
|
protected final String nullValue;
|
||||||
|
|
||||||
public DateFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
public DateFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
|
||||||
DateFormatter dateTimeFormatter, Resolution resolution, Map<String, String> meta) {
|
DateFormatter dateTimeFormatter, Resolution resolution, String nullValue,
|
||||||
|
Map<String, String> meta) {
|
||||||
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
this.dateTimeFormatter = dateTimeFormatter;
|
this.dateTimeFormatter = dateTimeFormatter;
|
||||||
this.dateMathParser = dateTimeFormatter.toDateMathParser();
|
this.dateMathParser = dateTimeFormatter.toDateMathParser();
|
||||||
this.resolution = resolution;
|
this.resolution = resolution;
|
||||||
|
this.nullValue = nullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateFieldType(String name) {
|
public DateFieldType(String name) {
|
||||||
this(name, true, false, true, DEFAULT_DATE_TIME_FORMATTER, Resolution.MILLISECONDS, Collections.emptyMap());
|
this(name, true, false, true, DEFAULT_DATE_TIME_FORMATTER, Resolution.MILLISECONDS, null, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateFieldType(String name, DateFormatter dateFormatter) {
|
public DateFieldType(String name, DateFormatter dateFormatter) {
|
||||||
this(name, true, false, true, dateFormatter, Resolution.MILLISECONDS, Collections.emptyMap());
|
this(name, true, false, true, dateFormatter, Resolution.MILLISECONDS, null, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateFieldType(String name, Resolution resolution) {
|
public DateFieldType(String name, Resolution resolution) {
|
||||||
this(name, true, false, true, DEFAULT_DATE_TIME_FORMATTER, resolution, Collections.emptyMap());
|
this(name, true, false, true, DEFAULT_DATE_TIME_FORMATTER, resolution, null, Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateFieldType(String name, Resolution resolution, DateFormatter dateFormatter) {
|
||||||
|
this(name, true, false, true, dateFormatter, resolution, null, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -316,6 +323,24 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
|
||||||
return resolution.convert(DateFormatters.from(dateTimeFormatter().parse(value), dateTimeFormatter().locale()).toInstant());
|
return resolution.convert(DateFormatters.from(dateTimeFormatter().parse(value), dateTimeFormatter().locale()).toInstant());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
DateFormatter defaultFormatter = dateTimeFormatter();
|
||||||
|
DateFormatter formatter = format != null
|
||||||
|
? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale())
|
||||||
|
: defaultFormatter;
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
public String parseSourceValue(Object value) {
|
||||||
|
String date = value.toString();
|
||||||
|
long timestamp = parse(date);
|
||||||
|
ZonedDateTime dateTime = resolution().toInstant(timestamp).atZone(ZoneOffset.UTC);
|
||||||
|
return formatter.format(dateTime);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, @Nullable QueryShardContext context) {
|
public Query termQuery(Object value, @Nullable QueryShardContext context) {
|
||||||
Query query = rangeQuery(value, value, true, true, ShapeRelation.INTERSECTS, null, null, context);
|
Query query = rangeQuery(value, value, true, true, ShapeRelation.INTERSECTS, null, null, context);
|
||||||
|
@ -609,24 +634,6 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
DateFormatter defaultFormatter = fieldType().dateTimeFormatter();
|
|
||||||
DateFormatter formatter = format != null
|
|
||||||
? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale())
|
|
||||||
: defaultFormatter;
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValueAsString) {
|
|
||||||
@Override
|
|
||||||
public String parseSourceValue(Object value) {
|
|
||||||
String date = value.toString();
|
|
||||||
long timestamp = fieldType().parse(date);
|
|
||||||
ZonedDateTime dateTime = fieldType().resolution().toInstant(timestamp).atZone(ZoneOffset.UTC);
|
|
||||||
return formatter.format(dateTime);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getIgnoreMalformed() {
|
public boolean getIgnoreMalformed() {
|
||||||
return ignoreMalformed;
|
return ignoreMalformed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.FieldType;
|
import org.apache.lucene.document.FieldType;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.elasticsearch.common.Nullable;
|
|
||||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||||
import org.elasticsearch.common.settings.Setting;
|
import org.elasticsearch.common.settings.Setting;
|
||||||
import org.elasticsearch.common.settings.Setting.Property;
|
import org.elasticsearch.common.settings.Setting.Property;
|
||||||
|
@ -34,8 +33,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.common.xcontent.support.AbstractXContentParser;
|
import org.elasticsearch.common.xcontent.support.AbstractXContentParser;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.index.mapper.FieldNamesFieldMapper.FieldNamesFieldType;
|
import org.elasticsearch.index.mapper.FieldNamesFieldMapper.FieldNamesFieldType;
|
||||||
import org.elasticsearch.search.fetch.subphase.FetchFieldsPhase;
|
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -276,11 +273,6 @@ public abstract class FieldMapper extends Mapper implements Cloneable {
|
||||||
*/
|
*/
|
||||||
protected abstract void parseCreateField(ParseContext context) throws IOException;
|
protected abstract void parseCreateField(ParseContext context) throws IOException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a helper class to fetch field values during the {@link FetchFieldsPhase}.
|
|
||||||
*/
|
|
||||||
public abstract ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, @Nullable String format);
|
|
||||||
|
|
||||||
protected final void createFieldNamesField(ParseContext context) {
|
protected final void createFieldNamesField(ParseContext context) {
|
||||||
assert fieldType().hasDocValues() == false : "_field_names should only be used when doc_values are turned off";
|
assert fieldType().hasDocValues() == false : "_field_names should only be used when doc_values are turned off";
|
||||||
FieldNamesFieldType fieldNamesFieldType = context.docMapper().metadataMapper(FieldNamesFieldMapper.class).fieldType();
|
FieldNamesFieldType fieldNamesFieldType = context.docMapper().metadataMapper(FieldNamesFieldMapper.class).fieldType();
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.common.Explicit;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -128,6 +129,11 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query existsQuery(QueryShardContext context) {
|
public Query existsQuery(QueryShardContext context) {
|
||||||
throw new UnsupportedOperationException("Cannot run exists query on _field_names");
|
throw new UnsupportedOperationException("Cannot run exists query on _field_names");
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class GeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper<Geomet
|
||||||
private final VectorGeoShapeQueryProcessor queryProcessor;
|
private final VectorGeoShapeQueryProcessor queryProcessor;
|
||||||
|
|
||||||
public GeoShapeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
public GeoShapeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, meta);
|
super(name, indexed, stored, hasDocValues, false, meta);
|
||||||
this.queryProcessor = new VectorGeoShapeQueryProcessor();
|
this.queryProcessor = new VectorGeoShapeQueryProcessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,11 @@ public class IdFieldMapper extends MetadataFieldMapper {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
return termsQuery(Arrays.asList(value), context);
|
return termsQuery(Arrays.asList(value), context);
|
||||||
|
|
|
@ -25,6 +25,7 @@ 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.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -74,6 +75,11 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
|
||||||
// field is bounded by the number of fields in the mappings.
|
// field is bounded by the number of fields in the mappings.
|
||||||
return new TermRangeQuery(name(), null, null, true, true);
|
return new TermRangeQuery(name(), null, null, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IgnoredFieldMapper() {
|
private IgnoredFieldMapper() {
|
||||||
|
|
|
@ -71,6 +71,11 @@ public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, Supplier<SearchLookup> searchLookup) {
|
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, Supplier<SearchLookup> searchLookup) {
|
||||||
return new ConstantIndexFieldData.Builder(mapperService -> fullyQualifiedIndexName, name(), CoreValuesSourceType.BYTES);
|
return new ConstantIndexFieldData.Builder(mapperService -> fullyQualifiedIndexName, name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IndexFieldMapper() {
|
public IndexFieldMapper() {
|
||||||
|
|
|
@ -111,7 +111,8 @@ public class IpFieldMapper extends ParametrizedFieldMapper {
|
||||||
@Override
|
@Override
|
||||||
public IpFieldMapper build(BuilderContext context) {
|
public IpFieldMapper build(BuilderContext context) {
|
||||||
return new IpFieldMapper(name,
|
return new IpFieldMapper(name,
|
||||||
new IpFieldType(buildFullName(context), indexed.getValue(), stored.getValue(), hasDocValues.getValue(), meta.getValue()),
|
new IpFieldType(buildFullName(context), indexed.getValue(), stored.getValue(),
|
||||||
|
hasDocValues.getValue(), parseNullValue(), meta.getValue()),
|
||||||
multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,12 +125,16 @@ public class IpFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
public static final class IpFieldType extends SimpleMappedFieldType {
|
public static final class IpFieldType extends SimpleMappedFieldType {
|
||||||
|
|
||||||
public IpFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
private final InetAddress nullValue;
|
||||||
|
|
||||||
|
public IpFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
|
||||||
|
InetAddress nullValue, Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
|
this.nullValue = nullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IpFieldType(String name) {
|
public IpFieldType(String name) {
|
||||||
this(name, true, false, true, Collections.emptyMap());
|
this(name, true, false, true, null, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -148,6 +153,25 @@ public class IpFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
InetAddress address;
|
||||||
|
if (value instanceof InetAddress) {
|
||||||
|
address = (InetAddress) value;
|
||||||
|
} else {
|
||||||
|
address = InetAddresses.forString(value.toString());
|
||||||
|
}
|
||||||
|
return InetAddresses.toAddrString(address);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, @Nullable QueryShardContext context) {
|
public Query termQuery(Object value, @Nullable QueryShardContext context) {
|
||||||
failIfNotIndexed();
|
failIfNotIndexed();
|
||||||
|
@ -411,25 +435,6 @@ public class IpFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
InetAddress address;
|
|
||||||
if (value instanceof InetAddress) {
|
|
||||||
address = (InetAddress) value;
|
|
||||||
} else {
|
|
||||||
address = InetAddresses.forString(value.toString());
|
|
||||||
}
|
|
||||||
return InetAddresses.toAddrString(address);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
return new Builder(simpleName(), ignoreMalformedByDefault, indexCreatedVersion).init(this);
|
return new Builder(simpleName(), ignoreMalformedByDefault, indexCreatedVersion).init(this);
|
||||||
|
|
|
@ -159,9 +159,7 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
else if (splitQueriesOnWhitespace.getValue()) {
|
else if (splitQueriesOnWhitespace.getValue()) {
|
||||||
searchAnalyzer = Lucene.WHITESPACE_ANALYZER;
|
searchAnalyzer = Lucene.WHITESPACE_ANALYZER;
|
||||||
}
|
}
|
||||||
return new KeywordFieldType(buildFullName(context), hasDocValues.getValue(), fieldType,
|
return new KeywordFieldType(buildFullName(context), fieldType, normalizer, searchAnalyzer, this);
|
||||||
eagerGlobalOrdinals.getValue(), normalizer, searchAnalyzer,
|
|
||||||
similarity.getValue(), boost.getValue(), meta.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -180,28 +178,48 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
public static final class KeywordFieldType extends StringFieldType {
|
public static final class KeywordFieldType extends StringFieldType {
|
||||||
|
|
||||||
public KeywordFieldType(String name, boolean hasDocValues, FieldType fieldType,
|
private final int ignoreAbove;
|
||||||
boolean eagerGlobalOrdinals, NamedAnalyzer normalizer, NamedAnalyzer searchAnalyzer,
|
private final String nullValue;
|
||||||
SimilarityProvider similarity, float boost, Map<String, String> meta) {
|
|
||||||
super(name, fieldType.indexOptions() != IndexOptions.NONE, fieldType.stored(),
|
public KeywordFieldType(String name, FieldType fieldType,
|
||||||
hasDocValues, new TextSearchInfo(fieldType, similarity, searchAnalyzer, searchAnalyzer), meta);
|
NamedAnalyzer normalizer, NamedAnalyzer searchAnalyzer, Builder builder) {
|
||||||
setEagerGlobalOrdinals(eagerGlobalOrdinals);
|
super(name,
|
||||||
|
fieldType.indexOptions() != IndexOptions.NONE,
|
||||||
|
fieldType.stored(),
|
||||||
|
builder.hasDocValues.getValue(),
|
||||||
|
new TextSearchInfo(fieldType, builder.similarity.getValue(), searchAnalyzer, searchAnalyzer),
|
||||||
|
builder.meta.getValue());
|
||||||
|
setEagerGlobalOrdinals(builder.eagerGlobalOrdinals.getValue());
|
||||||
setIndexAnalyzer(normalizer);
|
setIndexAnalyzer(normalizer);
|
||||||
setBoost(boost);
|
setBoost(builder.boost.getValue());
|
||||||
|
this.ignoreAbove = builder.ignoreAbove.getValue();
|
||||||
|
this.nullValue = builder.nullValue.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeywordFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) {
|
public KeywordFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) {
|
||||||
super(name, isSearchable, false, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, isSearchable, false, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
||||||
|
this.ignoreAbove = Integer.MAX_VALUE;
|
||||||
|
this.nullValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeywordFieldType(String name) {
|
public KeywordFieldType(String name) {
|
||||||
this(name, true, Defaults.FIELD_TYPE, false,
|
this(name, true, true, Collections.emptyMap());
|
||||||
Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, null, 1.0f, Collections.emptyMap());
|
}
|
||||||
|
|
||||||
|
public KeywordFieldType(String name, FieldType fieldType) {
|
||||||
|
super(name, fieldType.indexOptions() != IndexOptions.NONE,
|
||||||
|
false, false,
|
||||||
|
new TextSearchInfo(fieldType, null, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER),
|
||||||
|
Collections.emptyMap());
|
||||||
|
this.ignoreAbove = Integer.MAX_VALUE;
|
||||||
|
this.nullValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeywordFieldType(String name, NamedAnalyzer analyzer) {
|
public KeywordFieldType(String name, NamedAnalyzer analyzer) {
|
||||||
super(name, true, false, true, new TextSearchInfo(Defaults.FIELD_TYPE, null, analyzer, analyzer), Collections.emptyMap());
|
super(name, true, false, true, new TextSearchInfo(Defaults.FIELD_TYPE, null, analyzer, analyzer), Collections.emptyMap());
|
||||||
|
this.ignoreAbove = Integer.MAX_VALUE;
|
||||||
|
this.nullValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -219,6 +237,34 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
protected String parseSourceValue(Object value) {
|
||||||
|
String keywordValue = value.toString();
|
||||||
|
if (keywordValue.length() > ignoreAbove) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedAnalyzer normalizer = normalizer();
|
||||||
|
if (normalizer == null) {
|
||||||
|
return keywordValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return normalizeValue(normalizer, name(), keywordValue);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object valueForDisplay(Object value) {
|
public Object valueForDisplay(Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -317,7 +363,7 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
NamedAnalyzer normalizer = fieldType().normalizer();
|
NamedAnalyzer normalizer = fieldType().normalizer();
|
||||||
if (normalizer != null) {
|
if (normalizer != null) {
|
||||||
value = normalizeValue(normalizer, value);
|
value = normalizeValue(normalizer, name(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert to utf8 only once before feeding postings/dv/stored fields
|
// convert to utf8 only once before feeding postings/dv/stored fields
|
||||||
|
@ -336,8 +382,8 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String normalizeValue(NamedAnalyzer normalizer, String value) throws IOException {
|
private static String normalizeValue(NamedAnalyzer normalizer, String field, String value) throws IOException {
|
||||||
try (TokenStream ts = normalizer.tokenStream(name(), value)) {
|
try (TokenStream ts = normalizer.tokenStream(field, value)) {
|
||||||
final CharTermAttribute termAtt = ts.addAttribute(CharTermAttribute.class);
|
final CharTermAttribute termAtt = ts.addAttribute(CharTermAttribute.class);
|
||||||
ts.reset();
|
ts.reset();
|
||||||
if (ts.incrementToken() == false) {
|
if (ts.incrementToken() == false) {
|
||||||
|
@ -356,34 +402,6 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected String parseSourceValue(Object value) {
|
|
||||||
String keywordValue = value.toString();
|
|
||||||
if (keywordValue.length() > ignoreAbove) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
NamedAnalyzer normalizer = fieldType().normalizer();
|
|
||||||
if (normalizer == null) {
|
|
||||||
return keywordValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return normalizeValue(normalizer, keywordValue);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -330,7 +330,7 @@ public class LegacyGeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper<
|
||||||
private final LegacyGeoShapeQueryProcessor queryProcessor;
|
private final LegacyGeoShapeQueryProcessor queryProcessor;
|
||||||
|
|
||||||
private GeoShapeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
private GeoShapeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, meta);
|
super(name, indexed, stored, hasDocValues, false, meta);
|
||||||
this.queryProcessor = new LegacyGeoShapeQueryProcessor(this);
|
this.queryProcessor = new LegacyGeoShapeQueryProcessor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ import org.elasticsearch.index.query.QueryRewriteContext;
|
||||||
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 org.elasticsearch.search.DocValueFormat;
|
import org.elasticsearch.search.DocValueFormat;
|
||||||
|
import org.elasticsearch.search.fetch.subphase.FetchFieldsPhase;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -99,6 +100,11 @@ public abstract class MappedFieldType {
|
||||||
throw new IllegalArgumentException("Fielddata is not supported on field [" + name() + "] of type [" + typeName() + "]");
|
throw new IllegalArgumentException("Fielddata is not supported on field [" + name() + "] of type [" + typeName() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a helper class to fetch field values during the {@link FetchFieldsPhase}.
|
||||||
|
*/
|
||||||
|
public abstract ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, @Nullable String format);
|
||||||
|
|
||||||
/** Returns the name of this type, as would be specified in mapping properties */
|
/** Returns the name of this type, as would be specified in mapping properties */
|
||||||
public abstract String typeName();
|
public abstract String typeName();
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.index.mapper;
|
||||||
import org.elasticsearch.common.Explicit;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -176,8 +175,4 @@ public abstract class MetadataFieldMapper extends ParametrizedFieldMapper {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
|
||||||
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,9 +127,8 @@ public class NumberFieldMapper extends ParametrizedFieldMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NumberFieldMapper build(BuilderContext context) {
|
public NumberFieldMapper build(BuilderContext context) {
|
||||||
return new NumberFieldMapper(name,
|
MappedFieldType ft = new NumberFieldType(buildFullName(context), this);
|
||||||
new NumberFieldType(buildFullName(context), type, indexed.getValue(), stored.getValue(), hasDocValues.getValue(),
|
return new NumberFieldMapper(name, ft, multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
||||||
meta.getValue()), multiFieldsBuilder.build(this, context), copyTo.build(), this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,16 +892,25 @@ public class NumberFieldMapper extends ParametrizedFieldMapper {
|
||||||
public static final class NumberFieldType extends SimpleMappedFieldType {
|
public static final class NumberFieldType extends SimpleMappedFieldType {
|
||||||
|
|
||||||
private final NumberType type;
|
private final NumberType type;
|
||||||
|
private final boolean coerce;
|
||||||
|
private final Number nullValue;
|
||||||
|
|
||||||
public NumberFieldType(String name, NumberType type, boolean isSearchable, boolean isStored,
|
public NumberFieldType(String name, NumberType type, boolean isSearchable, boolean isStored,
|
||||||
boolean hasDocValues, Map<String, String> meta) {
|
boolean hasDocValues, boolean coerce, Number nullValue, Map<String, String> meta) {
|
||||||
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
this.type = Objects.requireNonNull(type);
|
this.type = Objects.requireNonNull(type);
|
||||||
|
this.coerce = coerce;
|
||||||
|
this.nullValue = nullValue;
|
||||||
this.setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); // allows number fields in significant text aggs - do we need this?
|
this.setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); // allows number fields in significant text aggs - do we need this?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NumberFieldType(String name, Builder builder) {
|
||||||
|
this(name, builder.type, builder.indexed.getValue(), builder.stored.getValue(), builder.hasDocValues.getValue(),
|
||||||
|
builder.coerce.getValue().value(), builder.nullValue.getValue(), builder.meta.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public NumberFieldType(String name, NumberType type) {
|
public NumberFieldType(String name, NumberType type) {
|
||||||
this(name, type, true, false, true, Collections.emptyMap());
|
this(name, type, true, false, true, true, null, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -966,6 +974,23 @@ public class NumberFieldMapper extends ParametrizedFieldMapper {
|
||||||
return type.valueForSearch((Number) value);
|
return type.valueForSearch((Number) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
if (value.equals("")) {
|
||||||
|
return nullValue;
|
||||||
|
}
|
||||||
|
return type.parse(value, coerce);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
|
public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
|
||||||
if (timeZone != null) {
|
if (timeZone != null) {
|
||||||
|
@ -1084,23 +1109,6 @@ public class NumberFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
if (value.equals("")) {
|
|
||||||
return nullValue;
|
|
||||||
}
|
|
||||||
return fieldType().type.parse(value, coerce.value());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
public ParametrizedFieldMapper.Builder getMergeBuilder() {
|
||||||
return new Builder(simpleName(), type, ignoreMalformedByDefault, coerceByDefault).init(this);
|
return new Builder(simpleName(), type, ignoreMalformedByDefault, coerceByDefault).init(this);
|
||||||
|
|
|
@ -137,14 +137,14 @@ public class RangeFieldMapper extends ParametrizedFieldMapper {
|
||||||
dateTimeFormatter = DateFormatter.forPattern(format.getValue()).withLocale(locale.getValue());
|
dateTimeFormatter = DateFormatter.forPattern(format.getValue()).withLocale(locale.getValue());
|
||||||
}
|
}
|
||||||
return new RangeFieldType(buildFullName(context), index.getValue(), store.getValue(), hasDocValues.getValue(),
|
return new RangeFieldType(buildFullName(context), index.getValue(), store.getValue(), hasDocValues.getValue(),
|
||||||
dateTimeFormatter, meta.getValue());
|
dateTimeFormatter, coerce.getValue().value(), meta.getValue());
|
||||||
}
|
}
|
||||||
if (type == RangeType.DATE) {
|
if (type == RangeType.DATE) {
|
||||||
return new RangeFieldType(buildFullName(context), index.getValue(), store.getValue(), hasDocValues.getValue(),
|
return new RangeFieldType(buildFullName(context), index.getValue(), store.getValue(), hasDocValues.getValue(),
|
||||||
Defaults.DATE_FORMATTER, meta.getValue());
|
Defaults.DATE_FORMATTER, coerce.getValue().value(), meta.getValue());
|
||||||
}
|
}
|
||||||
return new RangeFieldType(buildFullName(context), type, index.getValue(), store.getValue(), hasDocValues.getValue(),
|
return new RangeFieldType(buildFullName(context), type, index.getValue(), store.getValue(), hasDocValues.getValue(),
|
||||||
meta.getValue());
|
coerce.getValue().value(), meta.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,32 +159,35 @@ public class RangeFieldMapper extends ParametrizedFieldMapper {
|
||||||
protected final RangeType rangeType;
|
protected final RangeType rangeType;
|
||||||
protected final DateFormatter dateTimeFormatter;
|
protected final DateFormatter dateTimeFormatter;
|
||||||
protected final DateMathParser dateMathParser;
|
protected final DateMathParser dateMathParser;
|
||||||
|
protected final boolean coerce;
|
||||||
|
|
||||||
public RangeFieldType(String name, RangeType type, boolean indexed, boolean stored,
|
public RangeFieldType(String name, RangeType type, boolean indexed, boolean stored,
|
||||||
boolean hasDocValues, Map<String, String> meta) {
|
boolean hasDocValues, boolean coerce, Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
assert type != RangeType.DATE;
|
assert type != RangeType.DATE;
|
||||||
this.rangeType = Objects.requireNonNull(type);
|
this.rangeType = Objects.requireNonNull(type);
|
||||||
dateTimeFormatter = null;
|
dateTimeFormatter = null;
|
||||||
dateMathParser = null;
|
dateMathParser = null;
|
||||||
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
||||||
|
this.coerce = coerce;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RangeFieldType(String name, RangeType type) {
|
public RangeFieldType(String name, RangeType type) {
|
||||||
this(name, type, true, false, true, Collections.emptyMap());
|
this(name, type, true, false, true, false, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public RangeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, DateFormatter formatter,
|
public RangeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, DateFormatter formatter,
|
||||||
Map<String, String> meta) {
|
boolean coerce, Map<String, String> meta) {
|
||||||
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
this.rangeType = RangeType.DATE;
|
this.rangeType = RangeType.DATE;
|
||||||
this.dateTimeFormatter = Objects.requireNonNull(formatter);
|
this.dateTimeFormatter = Objects.requireNonNull(formatter);
|
||||||
this.dateMathParser = dateTimeFormatter.toDateMathParser();
|
this.dateMathParser = dateTimeFormatter.toDateMathParser();
|
||||||
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
||||||
|
this.coerce = coerce;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RangeFieldType(String name, DateFormatter formatter) {
|
public RangeFieldType(String name, DateFormatter formatter) {
|
||||||
this(name, true, false, true, formatter, Collections.emptyMap());
|
this(name, true, false, true, formatter, false, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public RangeType rangeType() { return rangeType; }
|
public RangeType rangeType() { return rangeType; }
|
||||||
|
@ -195,6 +198,37 @@ public class RangeFieldMapper extends ParametrizedFieldMapper {
|
||||||
return new BinaryIndexFieldData.Builder(name(), CoreValuesSourceType.RANGE);
|
return new BinaryIndexFieldData.Builder(name(), CoreValuesSourceType.RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
DateFormatter defaultFormatter = dateTimeFormatter();
|
||||||
|
DateFormatter formatter = format != null
|
||||||
|
? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale())
|
||||||
|
: defaultFormatter;
|
||||||
|
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
RangeType rangeType = rangeType();
|
||||||
|
if (!(value instanceof Map)) {
|
||||||
|
assert rangeType == RangeType.IP;
|
||||||
|
Tuple<InetAddress, Integer> ipRange = InetAddresses.parseCidr(value.toString());
|
||||||
|
return InetAddresses.toCidrString(ipRange.v1(), ipRange.v2());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> range = (Map<String, Object>) value;
|
||||||
|
Map<String, Object> parsedRange = new HashMap<>();
|
||||||
|
for (Map.Entry<String, Object> entry : range.entrySet()) {
|
||||||
|
Object parsedValue = rangeType.parseValue(entry.getValue(), coerce, dateMathParser);
|
||||||
|
Object formattedValue = rangeType.formatValue(parsedValue, formatter);
|
||||||
|
parsedRange.put(entry.getKey(), formattedValue);
|
||||||
|
}
|
||||||
|
return parsedRange;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return rangeType.name;
|
return rangeType.name;
|
||||||
|
@ -362,37 +396,6 @@ public class RangeFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
DateFormatter defaultFormatter = fieldType().dateTimeFormatter();
|
|
||||||
DateFormatter formatter = format != null
|
|
||||||
? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale())
|
|
||||||
: defaultFormatter;
|
|
||||||
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
RangeType rangeType = fieldType().rangeType();
|
|
||||||
if (!(value instanceof Map)) {
|
|
||||||
assert rangeType == RangeType.IP;
|
|
||||||
Tuple<InetAddress, Integer> ipRange = InetAddresses.parseCidr(value.toString());
|
|
||||||
return InetAddresses.toCidrString(ipRange.v1(), ipRange.v2());
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> range = (Map<String, Object>) value;
|
|
||||||
Map<String, Object> parsedRange = new HashMap<>();
|
|
||||||
for (Map.Entry<String, Object> entry : range.entrySet()) {
|
|
||||||
Object parsedValue = rangeType.parseValue(entry.getValue(), coerce.value(), fieldType().dateMathParser);
|
|
||||||
Object formattedValue = rangeType.formatValue(parsedValue, formatter);
|
|
||||||
parsedRange.put(entry.getKey(), formattedValue);
|
|
||||||
}
|
|
||||||
return parsedRange;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Range parseIpRangeFromCidr(final XContentParser parser) throws IOException {
|
private static Range parseIpRangeFromCidr(final XContentParser parser) throws IOException {
|
||||||
final Tuple<InetAddress, Integer> cidr = InetAddresses.parseCidr(parser.text());
|
final Tuple<InetAddress, Integer> cidr = InetAddresses.parseCidr(parser.text());
|
||||||
// create the lower value by zeroing out the host portion, upper value by filling it with all ones.
|
// create the lower value by zeroing out the host portion, upper value by filling it with all ones.
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.FieldType;
|
import org.apache.lucene.document.FieldType;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -92,6 +93,11 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean required;
|
private final boolean required;
|
||||||
|
|
|
@ -122,6 +122,11 @@ public class SeqNoFieldMapper extends MetadataFieldMapper {
|
||||||
return Long.parseLong(value.toString());
|
return Long.parseLong(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, @Nullable QueryShardContext context) {
|
public Query termQuery(Object value, @Nullable QueryShardContext context) {
|
||||||
long v = parse(value);
|
long v = parse(value);
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||||
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 org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -110,6 +111,11 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query existsQuery(QueryShardContext context) {
|
public Query existsQuery(QueryShardContext context) {
|
||||||
throw new QueryShardException(context, "The _source field is not searchable");
|
throw new QueryShardException(context, "The _source field is not searchable");
|
||||||
|
|
|
@ -394,6 +394,11 @@ public class TextFieldMapper extends FieldMapper {
|
||||||
return "phrase";
|
return "phrase";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query existsQuery(QueryShardContext context) {
|
public Query existsQuery(QueryShardContext context) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
@ -415,6 +420,11 @@ public class TextFieldMapper extends FieldMapper {
|
||||||
this.hasPositions = hasPositions;
|
this.hasPositions = hasPositions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
static boolean canMerge(PrefixFieldType first, PrefixFieldType second) {
|
static boolean canMerge(PrefixFieldType first, PrefixFieldType second) {
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
return second == null;
|
return second == null;
|
||||||
|
@ -510,11 +520,6 @@ public class TextFieldMapper extends FieldMapper {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
||||||
|
|
||||||
|
@ -541,11 +546,6 @@ public class TextFieldMapper extends FieldMapper {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
||||||
|
|
||||||
|
@ -640,6 +640,19 @@ public class TextFieldMapper extends FieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, QueryShardContext context) {
|
public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, boolean caseInsensitive, QueryShardContext context) {
|
||||||
if (prefixFieldType == null || prefixFieldType.accept(value.length()) == false) {
|
if (prefixFieldType == null || prefixFieldType.accept(value.length()) == false) {
|
||||||
|
@ -836,19 +849,6 @@ public class TextFieldMapper extends FieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Mapper> iterator() {
|
public Iterator<Mapper> iterator() {
|
||||||
List<Mapper> subIterators = new ArrayList<>();
|
List<Mapper> subIterators = new ArrayList<>();
|
||||||
|
|
|
@ -99,6 +99,11 @@ public class TypeFieldMapper extends MetadataFieldMapper {
|
||||||
return new ConstantIndexFieldData.Builder(typeFunction, name(), CoreValuesSourceType.BYTES);
|
return new ConstantIndexFieldData.Builder(typeFunction, name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSearchable() {
|
public boolean isSearchable() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -27,8 +27,8 @@ import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for fetching field values during the {@link FetchFieldsPhase}. Each {@link FieldMapper}
|
* A helper class for fetching field values during the {@link FetchFieldsPhase}. Each {@link MappedFieldType}
|
||||||
* is in charge of defining a value fetcher through {@link FieldMapper#valueFetcher}.
|
* is in charge of defining a value fetcher through {@link MappedFieldType#valueFetcher}.
|
||||||
*/
|
*/
|
||||||
public interface ValueFetcher {
|
public interface ValueFetcher {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.lucene.search.Query;
|
||||||
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 org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -53,6 +54,11 @@ public class VersionFieldMapper extends MetadataFieldMapper {
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
throw new QueryShardException(context, "The _version field is not searchable");
|
throw new QueryShardException(context, "The _version field is not searchable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) {
|
||||||
|
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private VersionFieldMapper() {
|
private VersionFieldMapper() {
|
||||||
|
|
|
@ -21,11 +21,8 @@ package org.elasticsearch.search.fetch.subphase;
|
||||||
|
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.elasticsearch.common.document.DocumentField;
|
import org.elasticsearch.common.document.DocumentField;
|
||||||
import org.elasticsearch.index.mapper.FieldAliasMapper;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
import org.elasticsearch.index.mapper.MappingLookup;
|
|
||||||
import org.elasticsearch.index.mapper.ValueFetcher;
|
import org.elasticsearch.index.mapper.ValueFetcher;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
import org.elasticsearch.search.lookup.SourceLookup;
|
||||||
|
@ -46,7 +43,7 @@ public class FieldFetcher {
|
||||||
public static FieldFetcher create(MapperService mapperService,
|
public static FieldFetcher create(MapperService mapperService,
|
||||||
SearchLookup searchLookup,
|
SearchLookup searchLookup,
|
||||||
Collection<FieldAndFormat> fieldAndFormats) {
|
Collection<FieldAndFormat> fieldAndFormats) {
|
||||||
MappingLookup fieldMappers = mapperService.documentMapper().mappers();
|
|
||||||
List<FieldContext> fieldContexts = new ArrayList<>();
|
List<FieldContext> fieldContexts = new ArrayList<>();
|
||||||
|
|
||||||
for (FieldAndFormat fieldAndFormat : fieldAndFormats) {
|
for (FieldAndFormat fieldAndFormat : fieldAndFormats) {
|
||||||
|
@ -55,19 +52,11 @@ public class FieldFetcher {
|
||||||
|
|
||||||
Collection<String> concreteFields = mapperService.simpleMatchToFullName(fieldPattern);
|
Collection<String> concreteFields = mapperService.simpleMatchToFullName(fieldPattern);
|
||||||
for (String field : concreteFields) {
|
for (String field : concreteFields) {
|
||||||
Mapper mapper = fieldMappers.getMapper(field);
|
MappedFieldType ft = mapperService.fieldType(field);
|
||||||
if (mapper == null || mapperService.isMetadataField(field)) {
|
if (ft == null || mapperService.isMetadataField(field)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ValueFetcher valueFetcher = ft.valueFetcher(mapperService, searchLookup, format);
|
||||||
if (mapper instanceof FieldAliasMapper) {
|
|
||||||
String target = ((FieldAliasMapper) mapper).path();
|
|
||||||
mapper = fieldMappers.getMapper(target);
|
|
||||||
assert mapper instanceof FieldMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldMapper fieldMapper = (FieldMapper) mapper;
|
|
||||||
ValueFetcher valueFetcher = fieldMapper.valueFetcher(mapperService, searchLookup, format);
|
|
||||||
fieldContexts.add(new FieldContext(field, valueFetcher));
|
fieldContexts.add(new FieldContext(field, valueFetcher));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ 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.ParametrizedFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.TextSearchInfo;
|
import org.elasticsearch.index.mapper.TextSearchInfo;
|
||||||
|
import org.elasticsearch.index.mapper.ValueFetcher;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.indices.IndexTemplateMissingException;
|
import org.elasticsearch.indices.IndexTemplateMissingException;
|
||||||
import org.elasticsearch.indices.IndicesService;
|
import org.elasticsearch.indices.IndicesService;
|
||||||
|
@ -54,6 +55,7 @@ import org.elasticsearch.indices.InvalidIndexTemplateException;
|
||||||
import org.elasticsearch.indices.SystemIndices;
|
import org.elasticsearch.indices.SystemIndices;
|
||||||
import org.elasticsearch.plugins.MapperPlugin;
|
import org.elasticsearch.plugins.MapperPlugin;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -1586,6 +1588,11 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase {
|
||||||
|
|
||||||
public MetadataTimestampFieldMapper(boolean enabled) {
|
public MetadataTimestampFieldMapper(boolean enabled) {
|
||||||
super(new MappedFieldType("_data_stream_timestamp", false, false, false, TextSearchInfo.NONE, Collections.emptyMap()) {
|
super(new MappedFieldType("_data_stream_timestamp", false, false, false, TextSearchInfo.NONE, Collections.emptyMap()) {
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return "_data_stream_timestamp";
|
return "_data_stream_timestamp";
|
||||||
|
|
|
@ -312,17 +312,17 @@ public class IndexFieldDataServiceTests extends ESSingleNodeTestCase {
|
||||||
public void testRequireDocValuesOnLongs() {
|
public void testRequireDocValuesOnLongs() {
|
||||||
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG));
|
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG));
|
||||||
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG,
|
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG,
|
||||||
true, false, false, Collections.emptyMap()));
|
true, false, false, false, null, Collections.emptyMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRequireDocValuesOnDoubles() {
|
public void testRequireDocValuesOnDoubles() {
|
||||||
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.DOUBLE));
|
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.DOUBLE));
|
||||||
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.DOUBLE,
|
doTestRequireDocValues(new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.DOUBLE,
|
||||||
true, false, false, Collections.emptyMap()));
|
true, false, false, false, null, Collections.emptyMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRequireDocValuesOnBools() {
|
public void testRequireDocValuesOnBools() {
|
||||||
doTestRequireDocValues(new BooleanFieldMapper.BooleanFieldType("field"));
|
doTestRequireDocValues(new BooleanFieldMapper.BooleanFieldType("field"));
|
||||||
doTestRequireDocValues(new BooleanFieldMapper.BooleanFieldType("field", true, false, false, Collections.emptyMap()));
|
doTestRequireDocValues(new BooleanFieldMapper.BooleanFieldType("field", true, false, false, null, Collections.emptyMap()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,19 +27,13 @@ import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.BoostQuery;
|
import org.apache.lucene.search.BoostQuery;
|
||||||
import org.apache.lucene.search.TermQuery;
|
import org.apache.lucene.search.TermQuery;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.index.mapper.ParseContext.Document;
|
import org.elasticsearch.index.mapper.ParseContext.Document;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class BooleanFieldMapperTests extends MapperTestCase {
|
public class BooleanFieldMapperTests extends MapperTestCase {
|
||||||
|
|
||||||
|
@ -198,20 +192,4 @@ public class BooleanFieldMapperTests extends MapperTestCase {
|
||||||
assertEquals(new BoostQuery(new TermQuery(new Term("field", "T")), 2.0f), ft.termQuery("true", null));
|
assertEquals(new BoostQuery(new TermQuery(new Term("field", "T")), 2.0f), ft.termQuery("true", null));
|
||||||
assertParseMaximalWarnings();
|
assertParseMaximalWarnings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
BooleanFieldMapper mapper = new BooleanFieldMapper.Builder("field").build(context);
|
|
||||||
assertEquals(List.of(true), fetchSourceValue(mapper, true));
|
|
||||||
assertEquals(List.of(false), fetchSourceValue(mapper, "false"));
|
|
||||||
assertEquals(List.of(false), fetchSourceValue(mapper, ""));
|
|
||||||
|
|
||||||
Map<String, Object> mapping = org.elasticsearch.common.collect.Map.of("type", "boolean", "null_value", true);
|
|
||||||
BooleanFieldMapper.Builder builder = new BooleanFieldMapper.Builder("field");
|
|
||||||
builder.parse("field", null, new HashMap<>(mapping));
|
|
||||||
BooleanFieldMapper nullValueMapper = builder.build(context);
|
|
||||||
assertEquals(List.of(true), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.TermQuery;
|
import org.apache.lucene.search.TermQuery;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
public class BooleanFieldTypeTests extends FieldTypeTestCase {
|
public class BooleanFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
@ -45,9 +46,22 @@ public class BooleanFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertEquals(new TermQuery(new Term("field", "T")), ft.termQuery("true", null));
|
assertEquals(new TermQuery(new Term("field", "T")), ft.termQuery("true", null));
|
||||||
assertEquals(new TermQuery(new Term("field", "F")), ft.termQuery("false", null));
|
assertEquals(new TermQuery(new Term("field", "F")), ft.termQuery("false", null));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new BooleanFieldMapper.BooleanFieldType("field", false, false, true, Collections.emptyMap());
|
MappedFieldType unsearchable = new BooleanFieldMapper.BooleanFieldType("field", false);
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.termQuery("true", null));
|
() -> unsearchable.termQuery("true", null));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
|
||||||
|
MappedFieldType fieldType = new BooleanFieldMapper.BooleanFieldType("field");
|
||||||
|
assertEquals(Collections.singletonList(true), fetchSourceValue(fieldType, true));
|
||||||
|
assertEquals(Collections.singletonList(false), fetchSourceValue(fieldType, "false"));
|
||||||
|
assertEquals(Collections.singletonList(false), fetchSourceValue(fieldType, ""));
|
||||||
|
|
||||||
|
MappedFieldType nullFieldType = new BooleanFieldMapper.BooleanFieldType(
|
||||||
|
"field", true, false, true, true, Collections.emptyMap()
|
||||||
|
);
|
||||||
|
assertEquals(Collections.singletonList(true), fetchSourceValue(nullFieldType, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,8 @@ import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.CharsRefBuilder;
|
import org.apache.lucene.util.CharsRefBuilder;
|
||||||
import org.apache.lucene.util.automaton.Operations;
|
import org.apache.lucene.util.automaton.Operations;
|
||||||
import org.apache.lucene.util.automaton.RegExp;
|
import org.apache.lucene.util.automaton.RegExp;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
@ -54,7 +51,6 @@ import org.hamcrest.core.CombinableMatcher;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@ -751,22 +747,6 @@ public class CompletionFieldMapperTests extends MapperTestCase {
|
||||||
"The maximum allowed number of completion contexts in a mapping will be limited to [10] starting in version [8.0].");
|
"The maximum allowed number of completion contexts in a mapping will be limited to [10] starting in version [8.0].");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
NamedAnalyzer defaultAnalyzer = new NamedAnalyzer("standard", AnalyzerScope.INDEX, new StandardAnalyzer());
|
|
||||||
CompletionFieldMapper mapper = new CompletionFieldMapper.Builder("completion", defaultAnalyzer, Version.CURRENT).build(context);
|
|
||||||
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("value"), fetchSourceValue(mapper, "value"));
|
|
||||||
|
|
||||||
List<String> list = org.elasticsearch.common.collect.List.of("first", "second");
|
|
||||||
assertEquals(list, fetchSourceValue(mapper, list));
|
|
||||||
|
|
||||||
Map<String, Object> object = org.elasticsearch.common.collect.Map.of(
|
|
||||||
"input", org.elasticsearch.common.collect.List.of("first", "second"), "weight", "2.718");
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(object), fetchSourceValue(mapper, object));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Matcher<IndexableField> suggestField(String value) {
|
private Matcher<IndexableField> suggestField(String value) {
|
||||||
return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)),
|
return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)),
|
||||||
Matchers.instanceOf(SuggestField.class));
|
Matchers.instanceOf(SuggestField.class));
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||||
|
import org.elasticsearch.index.analysis.AnalyzerScope;
|
||||||
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CompletionFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
NamedAnalyzer defaultAnalyzer = new NamedAnalyzer("standard", AnalyzerScope.INDEX, new StandardAnalyzer());
|
||||||
|
|
||||||
|
MappedFieldType fieldType = new CompletionFieldMapper.CompletionFieldType("name", defaultAnalyzer, Collections.emptyMap());
|
||||||
|
|
||||||
|
assertEquals(Collections.singletonList("value"), fetchSourceValue(fieldType, "value"));
|
||||||
|
|
||||||
|
List<String> list = Arrays.asList("first", "second");
|
||||||
|
assertEquals(list, fetchSourceValue(fieldType, list));
|
||||||
|
|
||||||
|
Map<String, Object> object = new HashMap<>();
|
||||||
|
object.put("input", Arrays.asList("first", "second"));
|
||||||
|
object.put("weight", "2.718");
|
||||||
|
assertEquals(Collections.singletonList(object), fetchSourceValue(fieldType, object));
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,14 +21,10 @@ package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.bootstrap.JavaVersion;
|
import org.elasticsearch.bootstrap.JavaVersion;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.collect.List;
|
import org.elasticsearch.common.collect.List;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.time.DateFormatter;
|
import org.elasticsearch.common.time.DateFormatter;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.index.mapper.DateFieldMapper.Resolution;
|
|
||||||
import org.elasticsearch.index.termvectors.TermVectorsService;
|
import org.elasticsearch.index.termvectors.TermVectorsService;
|
||||||
import org.elasticsearch.search.DocValueFormat;
|
import org.elasticsearch.search.DocValueFormat;
|
||||||
|
|
||||||
|
@ -36,8 +32,6 @@ import java.io.IOException;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
@ -311,45 +305,7 @@ public class DateFieldMapperTests extends MapperTestCase {
|
||||||
assertThat(e.getMessage(), containsString("Error parsing [format] on field [field]: Invalid"));
|
assertThat(e.getMessage(), containsString("Error parsing [format] on field [field]: Invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
DateFieldMapper mapper = createMapper(Resolution.MILLISECONDS, null);
|
|
||||||
String date = "2020-05-15T21:33:02.000Z";
|
|
||||||
assertEquals(List.of(date), fetchSourceValue(mapper, date));
|
|
||||||
assertEquals(List.of(date), fetchSourceValue(mapper, 1589578382000L));
|
|
||||||
|
|
||||||
DateFieldMapper mapperWithFormat = createMapper(Resolution.MILLISECONDS, "yyyy/MM/dd||epoch_millis");
|
|
||||||
String dateInFormat = "1990/12/29";
|
|
||||||
assertEquals(List.of(dateInFormat), fetchSourceValue(mapperWithFormat, dateInFormat));
|
|
||||||
assertEquals(List.of(dateInFormat), fetchSourceValue(mapperWithFormat, 662428800000L));
|
|
||||||
|
|
||||||
DateFieldMapper mapperWithMillis = createMapper(Resolution.MILLISECONDS, "epoch_millis");
|
|
||||||
String dateInMillis = "662428800000";
|
|
||||||
assertEquals(List.of(dateInMillis), fetchSourceValue(mapperWithMillis, dateInMillis));
|
|
||||||
assertEquals(List.of(dateInMillis), fetchSourceValue(mapperWithMillis, 662428800000L));
|
|
||||||
|
|
||||||
String nullValueDate = "2020-05-15T21:33:02.000Z";
|
|
||||||
DateFieldMapper nullValueMapper = createMapper(Resolution.MILLISECONDS, null, nullValueDate);
|
|
||||||
assertEquals(List.of(nullValueDate), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testParseSourceValueWithFormat() throws IOException {
|
|
||||||
DateFieldMapper mapper = createMapper(Resolution.NANOSECONDS, "strict_date_time", "1970-12-29T00:00:00.000Z");
|
|
||||||
String date = "1990-12-29T00:00:00.000Z";
|
|
||||||
assertEquals(List.of("1990/12/29"), fetchSourceValue(mapper, date, "yyyy/MM/dd"));
|
|
||||||
assertEquals(List.of("662428800000"), fetchSourceValue(mapper, date, "epoch_millis"));
|
|
||||||
assertEquals(List.of("1970/12/29"), fetchSourceValue(mapper, null, "yyyy/MM/dd"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testParseSourceValueNanos() throws IOException {
|
|
||||||
DateFieldMapper mapper = createMapper(Resolution.NANOSECONDS, "strict_date_time||epoch_millis");
|
|
||||||
String date = "2020-05-15T21:33:02.123456789Z";
|
|
||||||
assertEquals(List.of("2020-05-15T21:33:02.123456789Z"), fetchSourceValue(mapper, date));
|
|
||||||
assertEquals(List.of("2020-05-15T21:33:02.123Z"), fetchSourceValue(mapper, 1589578382123L));
|
|
||||||
|
|
||||||
String nullValueDate = "2020-05-15T21:33:02.123456789Z";
|
|
||||||
DateFieldMapper nullValueMapper = createMapper(Resolution.NANOSECONDS, "strict_date_time||epoch_millis", nullValueDate);
|
|
||||||
assertEquals(List.of(nullValueDate), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testFetchDocValuesMillis() throws IOException {
|
public void testFetchDocValuesMillis() throws IOException {
|
||||||
MapperService mapperService = createMapperService(
|
MapperService mapperService = createMapperService(
|
||||||
|
@ -372,27 +328,4 @@ public class DateFieldMapperTests extends MapperTestCase {
|
||||||
assertEquals(List.of(date), fetchFromDocValues(mapperService, ft, format, date));
|
assertEquals(List.of(date), fetchFromDocValues(mapperService, ft, format, date));
|
||||||
assertEquals(List.of("2020-05-15T21:33:02.123Z"), fetchFromDocValues(mapperService, ft, format, 1589578382123L));
|
assertEquals(List.of("2020-05-15T21:33:02.123Z"), fetchFromDocValues(mapperService, ft, format, 1589578382123L));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateFieldMapper createMapper(Resolution resolution, String format) {
|
|
||||||
return createMapper(resolution, format, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DateFieldMapper createMapper(Resolution resolution, String format, String nullValue) {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
Map<String, Object> mapping = new HashMap<>();
|
|
||||||
mapping.put("type", "date_nanos");
|
|
||||||
if (format != null) {
|
|
||||||
mapping.put("format", format);
|
|
||||||
}
|
|
||||||
if (nullValue != null) {
|
|
||||||
mapping.put("null_value", nullValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
DateFieldMapper.Builder builder
|
|
||||||
= new DateFieldMapper.Builder("field", resolution, null, false, Version.CURRENT);
|
|
||||||
builder.parse("field", null, mapping);
|
|
||||||
return builder.build(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,14 +35,15 @@ import org.apache.lucene.store.Directory;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.time.DateFormatter;
|
||||||
import org.elasticsearch.common.time.DateFormatters;
|
import org.elasticsearch.common.time.DateFormatters;
|
||||||
import org.elasticsearch.common.time.DateMathParser;
|
import org.elasticsearch.common.time.DateMathParser;
|
||||||
import org.elasticsearch.common.util.BigArrays;
|
import org.elasticsearch.common.util.BigArrays;
|
||||||
import org.elasticsearch.core.internal.io.IOUtils;
|
import org.elasticsearch.core.internal.io.IOUtils;
|
||||||
import org.elasticsearch.index.IndexSettings;
|
import org.elasticsearch.index.IndexSettings;
|
||||||
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
|
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
|
||||||
import org.elasticsearch.index.fielddata.plain.SortedNumericIndexFieldData;
|
|
||||||
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
|
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
|
||||||
|
import org.elasticsearch.index.fielddata.plain.SortedNumericIndexFieldData;
|
||||||
import org.elasticsearch.index.mapper.DateFieldMapper.DateFieldType;
|
import org.elasticsearch.index.mapper.DateFieldMapper.DateFieldType;
|
||||||
import org.elasticsearch.index.mapper.DateFieldMapper.Resolution;
|
import org.elasticsearch.index.mapper.DateFieldMapper.Resolution;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType.Relation;
|
import org.elasticsearch.index.mapper.MappedFieldType.Relation;
|
||||||
|
@ -70,14 +71,12 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsFieldWithinQueryDateMillis() throws IOException {
|
public void testIsFieldWithinQueryDateMillis() throws IOException {
|
||||||
DateFieldType ft = new DateFieldType("my_date", true, false, true,
|
DateFieldType ft = new DateFieldType("my_date", Resolution.MILLISECONDS);
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, Resolution.MILLISECONDS, Collections.emptyMap());
|
|
||||||
isFieldWithinRangeTestCase(ft);
|
isFieldWithinRangeTestCase(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testIsFieldWithinQueryDateNanos() throws IOException {
|
public void testIsFieldWithinQueryDateNanos() throws IOException {
|
||||||
DateFieldType ft = new DateFieldType("my_date", true, false, true,
|
DateFieldType ft = new DateFieldType("my_date", Resolution.NANOSECONDS);
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, Resolution.NANOSECONDS, Collections.emptyMap());
|
|
||||||
isFieldWithinRangeTestCase(ft);
|
isFieldWithinRangeTestCase(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +175,7 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertEquals(expected, ft.termQuery(date, context));
|
assertEquals(expected, ft.termQuery(date, context));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new DateFieldType("field", false, false, true, DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
MappedFieldType unsearchable = new DateFieldType("field", false, false, true, DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
||||||
Resolution.MILLISECONDS, Collections.emptyMap());
|
Resolution.MILLISECONDS, null, Collections.emptyMap());
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.termQuery(date, context));
|
() -> unsearchable.termQuery(date, context));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -211,7 +210,7 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
|
||||||
ft.rangeQuery("now", instant2, true, true, null, null, null, context));
|
ft.rangeQuery("now", instant2, true, true, null, null, null, context));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new DateFieldType("field", false, false, true, DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
MappedFieldType unsearchable = new DateFieldType("field", false, false, true, DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
||||||
Resolution.MILLISECONDS, Collections.emptyMap());
|
Resolution.MILLISECONDS, null, Collections.emptyMap());
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.rangeQuery(date1, date2, true, true, null, null, null, context));
|
() -> unsearchable.rangeQuery(date1, date2, true, true, null, null, null, context));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -276,4 +275,49 @@ public class DateFieldTypeTests extends FieldTypeTestCase {
|
||||||
private Instant instant(String str) {
|
private Instant instant(String str) {
|
||||||
return DateFormatters.from(DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.parse(str)).toInstant();
|
return DateFormatters.from(DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.parse(str)).toInstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DateFieldType fieldType(Resolution resolution, String format, String nullValue) {
|
||||||
|
DateFormatter formatter = DateFormatter.forPattern(format);
|
||||||
|
return new DateFieldType("field", true, false, true, formatter, resolution, nullValue, Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
MappedFieldType fieldType = new DateFieldType("field", Resolution.MILLISECONDS);
|
||||||
|
String date = "2020-05-15T21:33:02.000Z";
|
||||||
|
assertEquals(Collections.singletonList(date), fetchSourceValue(fieldType, date));
|
||||||
|
assertEquals(Collections.singletonList(date), fetchSourceValue(fieldType, 1589578382000L));
|
||||||
|
|
||||||
|
MappedFieldType fieldWithFormat = fieldType(Resolution.MILLISECONDS, "yyyy/MM/dd||epoch_millis", null);
|
||||||
|
String dateInFormat = "1990/12/29";
|
||||||
|
assertEquals(Collections.singletonList(dateInFormat), fetchSourceValue(fieldWithFormat, dateInFormat));
|
||||||
|
assertEquals(Collections.singletonList(dateInFormat), fetchSourceValue(fieldWithFormat, 662428800000L));
|
||||||
|
|
||||||
|
MappedFieldType millis = fieldType(Resolution.MILLISECONDS, "epoch_millis", null);
|
||||||
|
String dateInMillis = "662428800000";
|
||||||
|
assertEquals(Collections.singletonList(dateInMillis), fetchSourceValue(millis, dateInMillis));
|
||||||
|
assertEquals(Collections.singletonList(dateInMillis), fetchSourceValue(millis, 662428800000L));
|
||||||
|
|
||||||
|
String nullValueDate = "2020-05-15T21:33:02.000Z";
|
||||||
|
MappedFieldType nullFieldType = fieldType(Resolution.MILLISECONDS, "strict_date_time", nullValueDate);
|
||||||
|
assertEquals(Collections.singletonList(nullValueDate), fetchSourceValue(nullFieldType, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseSourceValueWithFormat() throws IOException {
|
||||||
|
MappedFieldType mapper = fieldType(Resolution.NANOSECONDS, "strict_date_time", "1970-12-29T00:00:00.000Z");
|
||||||
|
String date = "1990-12-29T00:00:00.000Z";
|
||||||
|
assertEquals(Collections.singletonList("1990/12/29"), fetchSourceValue(mapper, date, "yyyy/MM/dd"));
|
||||||
|
assertEquals(Collections.singletonList("662428800000"), fetchSourceValue(mapper, date, "epoch_millis"));
|
||||||
|
assertEquals(Collections.singletonList("1970/12/29"), fetchSourceValue(mapper, null, "yyyy/MM/dd"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseSourceValueNanos() throws IOException {
|
||||||
|
MappedFieldType mapper = fieldType(Resolution.NANOSECONDS, "strict_date_time||epoch_millis", null);
|
||||||
|
String date = "2020-05-15T21:33:02.123456789Z";
|
||||||
|
assertEquals(Collections.singletonList("2020-05-15T21:33:02.123456789Z"), fetchSourceValue(mapper, date));
|
||||||
|
assertEquals(Collections.singletonList("2020-05-15T21:33:02.123Z"), fetchSourceValue(mapper, 1589578382123L));
|
||||||
|
|
||||||
|
String nullValueDate = "2020-05-15T21:33:02.123456789Z";
|
||||||
|
MappedFieldType nullValueMapper = fieldType(Resolution.NANOSECONDS, "strict_date_time||epoch_millis", nullValueDate);
|
||||||
|
assertEquals(Collections.singletonList(nullValueDate), fetchSourceValue(nullValueMapper, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,11 @@ public class DocumentFieldMapperTests extends LuceneTestCase {
|
||||||
super(name, true, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
|
super(name, true, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return "fake";
|
return "fake";
|
||||||
|
@ -86,11 +91,6 @@ public class DocumentFieldMapperTests extends LuceneTestCase {
|
||||||
protected void parseCreateField(ParseContext context) {
|
protected void parseCreateField(ParseContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -104,6 +104,16 @@ public class ExternalMapper extends ParametrizedFieldMapper {
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return "faketype";
|
return "faketype";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String generatedValue;
|
private final String generatedValue;
|
||||||
|
@ -165,16 +175,6 @@ public class ExternalMapper extends ParametrizedFieldMapper {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<Mapper> iterator() {
|
public Iterator<Mapper> iterator() {
|
||||||
return Iterators.concat(super.iterator(), Arrays.asList(binMapper, boolMapper, pointMapper, shapeMapper, stringMapper).iterator());
|
return Iterators.concat(super.iterator(), Arrays.asList(binMapper, boolMapper, pointMapper, shapeMapper, stringMapper).iterator());
|
||||||
|
|
|
@ -92,6 +92,16 @@ public class FakeStringFieldMapper extends FieldMapper {
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected String parseSourceValue(Object value) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FakeStringFieldMapper(FieldType fieldType, MappedFieldType mappedFieldType,
|
protected FakeStringFieldMapper(FieldType fieldType, MappedFieldType mappedFieldType,
|
||||||
|
@ -121,16 +131,6 @@ public class FakeStringFieldMapper extends FieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected String parseSourceValue(Object value) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
|
||||||
|
|
||||||
|
|
|
@ -19,19 +19,13 @@
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.geo.GeoPoint;
|
import org.elasticsearch.common.geo.GeoPoint;
|
||||||
import org.elasticsearch.common.geo.GeoUtils;
|
import org.elasticsearch.common.geo.GeoUtils;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.geometry.utils.Geohash.stringEncode;
|
import static org.elasticsearch.geometry.utils.Geohash.stringEncode;
|
||||||
|
@ -331,39 +325,6 @@ public class GeoPointFieldMapperTests extends FieldMapperTestCase2<GeoPointField
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
AbstractGeometryFieldMapper<?, ?> mapper = new GeoPointFieldMapper.Builder("field").build(context);
|
|
||||||
SourceLookup sourceLookup = new SourceLookup();
|
|
||||||
|
|
||||||
Map<String, Object> jsonPoint = org.elasticsearch.common.collect.Map.of("type", "Point", "coordinates", List.of(42.0, 27.1));
|
|
||||||
Map<String, Object> otherJsonPoint = org.elasticsearch.common.collect.Map.of("type", "Point", "coordinates", List.of(30.0, 50.0));
|
|
||||||
String wktPoint = "POINT (42.0 27.1)";
|
|
||||||
String otherWktPoint = "POINT (30.0 50.0)";
|
|
||||||
|
|
||||||
// Test a single point in [lon, lat] array format.
|
|
||||||
Object sourceValue = List.of(42.0, 27.1);
|
|
||||||
assertEquals(List.of(jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a single point in "lat, lon" string format.
|
|
||||||
sourceValue = "27.1,42.0";
|
|
||||||
assertEquals(List.of(jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a list of points in [lon, lat] array format.
|
|
||||||
sourceValue = List.of(List.of(42.0, 27.1), List.of(30.0, 50.0));
|
|
||||||
assertEquals(List.of(jsonPoint, otherJsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktPoint, otherWktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a single point in well-known text format.
|
|
||||||
sourceValue = "POINT (42.0 27.1)";
|
|
||||||
assertEquals(List.of(jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GeoPointFieldMapper.Builder newBuilder() {
|
protected GeoPointFieldMapper.Builder newBuilder() {
|
||||||
return new GeoPointFieldMapper.Builder("geo");
|
return new GeoPointFieldMapper.Builder("geo");
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GeoPointFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new GeoPointFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
|
||||||
|
Map<String, Object> jsonPoint = new HashMap<>();
|
||||||
|
jsonPoint.put("type", "Point");
|
||||||
|
jsonPoint.put("coordinates", Arrays.asList(42.0, 27.1));
|
||||||
|
Map<String, Object> otherJsonPoint = new HashMap<>();
|
||||||
|
otherJsonPoint.put("type", "Point");
|
||||||
|
otherJsonPoint.put("coordinates", Arrays.asList(30.0, 50.0));
|
||||||
|
String wktPoint = "POINT (42.0 27.1)";
|
||||||
|
String otherWktPoint = "POINT (30.0 50.0)";
|
||||||
|
|
||||||
|
// Test a single point in [lon, lat] array format.
|
||||||
|
Object sourceValue = Arrays.asList(42.0, 27.1);
|
||||||
|
assertEquals(Collections.singletonList(jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a single point in "lat, lon" string format.
|
||||||
|
sourceValue = "27.1,42.0";
|
||||||
|
assertEquals(Collections.singletonList(jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a list of points in [lon, lat] array format.
|
||||||
|
sourceValue = Arrays.asList(Arrays.asList(42.0, 27.1), Arrays.asList(30.0, 50.0));
|
||||||
|
assertEquals(Arrays.asList(jsonPoint, otherJsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Arrays.asList(wktPoint, otherWktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a single point in well-known text format.
|
||||||
|
sourceValue = "POINT (42.0 27.1)";
|
||||||
|
assertEquals(Collections.singletonList(jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,13 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Explicit;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
import org.elasticsearch.common.collect.List;
|
||||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
|
@ -34,7 +31,6 @@ import org.junit.Before;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
@ -237,39 +233,6 @@ public class GeoShapeFieldMapperTests extends FieldMapperTestCase2<GeoShapeField
|
||||||
assertThat(document.docs().get(0).getFields("field").length, equalTo(2));
|
assertThat(document.docs().get(0).getFields("field").length, equalTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
GeoShapeFieldMapper mapper = new GeoShapeFieldMapper.Builder("field").build(context);
|
|
||||||
|
|
||||||
Map<String, Object> jsonLineString = org.elasticsearch.common.collect.Map.of("type", "LineString", "coordinates",
|
|
||||||
List.of(List.of(42.0, 27.1), List.of(30.0, 50.0)));
|
|
||||||
Map<String, Object> jsonPoint = org.elasticsearch.common.collect.Map.of("type", "Point", "coordinates", List.of(14.0, 15.0));
|
|
||||||
String wktLineString = "LINESTRING (42.0 27.1, 30.0 50.0)";
|
|
||||||
String wktPoint = "POINT (14.0 15.0)";
|
|
||||||
|
|
||||||
// Test a single shape in geojson format.
|
|
||||||
Object sourceValue = jsonLineString;
|
|
||||||
assertEquals(List.of(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a list of shapes in geojson format.
|
|
||||||
sourceValue = List.of(jsonLineString, jsonPoint);
|
|
||||||
assertEquals(List.of(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a single shape in wkt format.
|
|
||||||
sourceValue = wktLineString;
|
|
||||||
assertEquals(List.of(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a list of shapes in wkt format.
|
|
||||||
sourceValue = List.of(wktLineString, wktPoint);
|
|
||||||
assertEquals(List.of(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean supportsMeta() {
|
protected boolean supportsMeta() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GeoShapeFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new GeoShapeFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
|
||||||
|
Map<String, Object> jsonLineString = org.elasticsearch.common.collect.Map.of(
|
||||||
|
"type", "LineString",
|
||||||
|
"coordinates", Arrays.asList(Arrays.asList(42.0, 27.1), Arrays.asList(30.0, 50.0)));
|
||||||
|
Map<String, Object> jsonPoint = org.elasticsearch.common.collect.Map.of(
|
||||||
|
"type", "Point",
|
||||||
|
"coordinates", Arrays.asList(14.0, 15.0));
|
||||||
|
String wktLineString = "LINESTRING (42.0 27.1, 30.0 50.0)";
|
||||||
|
String wktPoint = "POINT (14.0 15.0)";
|
||||||
|
|
||||||
|
// Test a single shape in geojson format.
|
||||||
|
Object sourceValue = jsonLineString;
|
||||||
|
assertEquals(Collections.singletonList(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a list of shapes in geojson format.
|
||||||
|
sourceValue = Arrays.asList(jsonLineString, jsonPoint);
|
||||||
|
assertEquals(Arrays.asList(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Arrays.asList(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a single shape in wkt format.
|
||||||
|
sourceValue = wktLineString;
|
||||||
|
assertEquals(Collections.singletonList(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a list of shapes in wkt format.
|
||||||
|
sourceValue = Arrays.asList(wktLineString, wktPoint);
|
||||||
|
assertEquals(Arrays.asList(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Arrays.asList(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,11 +26,7 @@ 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.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.network.InetAddresses;
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.index.termvectors.TermVectorsService;
|
import org.elasticsearch.index.termvectors.TermVectorsService;
|
||||||
|
|
||||||
|
@ -208,19 +204,4 @@ public class IpFieldMapperTests extends MapperTestCase {
|
||||||
}));
|
}));
|
||||||
assertWarnings("Error parsing [:1] as IP in [null_value] on field [field]); [null_value] will be ignored");
|
assertWarnings("Error parsing [:1] as IP in [null_value] on field [field]); [null_value] will be ignored");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
IpFieldMapper mapper = new IpFieldMapper.Builder("field", true, Version.CURRENT).build(context);
|
|
||||||
assertEquals(List.of("2001:db8::2:1"), fetchSourceValue(mapper, "2001:db8::2:1"));
|
|
||||||
assertEquals(List.of("2001:db8::2:1"), fetchSourceValue(mapper, "2001:db8:0:0:0:0:2:1"));
|
|
||||||
assertEquals(List.of("::1"), fetchSourceValue(mapper, "0:0:0:0:0:0:0:1"));
|
|
||||||
|
|
||||||
IpFieldMapper nullValueMapper = new IpFieldMapper.Builder("field", true, Version.CURRENT)
|
|
||||||
.nullValue("2001:db8:0:0:0:0:2:7")
|
|
||||||
.build(context);
|
|
||||||
assertEquals(List.of("2001:db8::2:7"), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,12 @@ import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.ConstantScoreQuery;
|
||||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
import org.elasticsearch.common.network.InetAddresses;
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -71,7 +75,7 @@ public class IpFieldTypeTests extends FieldTypeTestCase {
|
||||||
prefix = ip + "/16";
|
prefix = ip + "/16";
|
||||||
assertEquals(InetAddressPoint.newPrefixQuery("field", InetAddresses.forString(ip), 16), ft.termQuery(prefix, null));
|
assertEquals(InetAddressPoint.newPrefixQuery("field", InetAddresses.forString(ip), 16), ft.termQuery(prefix, null));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, Collections.emptyMap());
|
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, null, Collections.emptyMap());
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.termQuery("::1", null));
|
() -> unsearchable.termQuery("::1", null));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -174,9 +178,26 @@ public class IpFieldTypeTests extends FieldTypeTestCase {
|
||||||
InetAddresses.forString("2001:db8::")),
|
InetAddresses.forString("2001:db8::")),
|
||||||
ft.rangeQuery("::ffff:c0a8:107", "2001:db8::", true, true, null, null, null, null));
|
ft.rangeQuery("::ffff:c0a8:107", "2001:db8::", true, true, null, null, null, null));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, Collections.emptyMap());
|
MappedFieldType unsearchable = new IpFieldMapper.IpFieldType("field", false, false, true, null, Collections.emptyMap());
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.rangeQuery("::1", "2001::", true, true, null, null, null, null));
|
() -> unsearchable.rangeQuery("::1", "2001::", true, true, null, null, null, null));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper
|
||||||
|
= new IpFieldMapper.Builder("field", true, Version.CURRENT).build(context).fieldType();
|
||||||
|
assertEquals(Collections.singletonList("2001:db8::2:1"), fetchSourceValue(mapper, "2001:db8::2:1"));
|
||||||
|
assertEquals(Collections.singletonList("2001:db8::2:1"), fetchSourceValue(mapper, "2001:db8:0:0:0:0:2:1"));
|
||||||
|
assertEquals(Collections.singletonList("::1"), fetchSourceValue(mapper, "0:0:0:0:0:0:0:1"));
|
||||||
|
|
||||||
|
MappedFieldType nullValueMapper = new IpFieldMapper.Builder("field", true, Version.CURRENT)
|
||||||
|
.nullValue("2001:db8:0:0:0:0:2:7")
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList("2001:db8::2:7"), fetchSourceValue(nullValueMapper, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,10 @@ package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.compress.CompressedXContent;
|
import org.elasticsearch.common.compress.CompressedXContent;
|
||||||
import org.elasticsearch.common.network.InetAddresses;
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
@ -35,11 +31,9 @@ import org.elasticsearch.index.IndexService;
|
||||||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.elasticsearch.index.mapper.FieldMapperTestCase.fetchSourceValue;
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
public class IpRangeFieldMapperTests extends ESSingleNodeTestCase {
|
public class IpRangeFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
|
@ -86,14 +80,4 @@ public class IpRangeFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
assertThat(storedField.stringValue(), containsString(strVal));
|
assertThat(storedField.stringValue(), containsString(strVal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
RangeFieldMapper mapper = new RangeFieldMapper.Builder("field", RangeType.IP, true).build(context);
|
|
||||||
Map<String, Object> range = org.elasticsearch.common.collect.Map.of("gte", "2001:db8:0:0:0:0:2:1");
|
|
||||||
assertEquals(List.of(org.elasticsearch.common.collect.Map.of("gte", "2001:db8::2:1")), fetchSourceValue(mapper, range));
|
|
||||||
assertEquals(List.of("2001:db8::2:1/32"), fetchSourceValue(mapper, "2001:db8:0:0:0:0:2:1/32"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class IpRangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
RangeFieldMapper mapper = new RangeFieldMapper.Builder("field", RangeType.IP, true).build(context);
|
||||||
|
Map<String, Object> range = org.elasticsearch.common.collect.Map.of("gte", "2001:db8:0:0:0:0:2:1");
|
||||||
|
assertEquals(Collections.singletonList(org.elasticsearch.common.collect.Map.of("gte", "2001:db8::2:1")),
|
||||||
|
fetchSourceValue(mapper.fieldType(), range));
|
||||||
|
assertEquals(Collections.singletonList("2001:db8::2:1/32"), fetchSourceValue(mapper.fieldType(), "2001:db8:0:0:0:0:2:1/32"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,10 +31,7 @@ import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.index.IndexableFieldType;
|
import org.apache.lucene.index.IndexableFieldType;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.index.IndexSettings;
|
import org.elasticsearch.index.IndexSettings;
|
||||||
import org.elasticsearch.index.analysis.AnalyzerScope;
|
import org.elasticsearch.index.analysis.AnalyzerScope;
|
||||||
|
@ -467,35 +464,4 @@ public class KeywordFieldMapperTests extends MapperTestCase {
|
||||||
new String[] { "hello world" }
|
new String[] { "hello world" }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
KeywordFieldMapper mapper = new KeywordFieldMapper.Builder("field").build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("value"), fetchSourceValue(mapper, "value"));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("42"), fetchSourceValue(mapper, 42L));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("true"), fetchSourceValue(mapper, true));
|
|
||||||
|
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> fetchSourceValue(mapper, "value", "format"));
|
|
||||||
assertEquals("Field [field] of type [keyword] doesn't support formats.", e.getMessage());
|
|
||||||
|
|
||||||
KeywordFieldMapper ignoreAboveMapper = new KeywordFieldMapper.Builder("field")
|
|
||||||
.ignoreAbove(4)
|
|
||||||
.build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(), fetchSourceValue(ignoreAboveMapper, "value"));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("42"), fetchSourceValue(ignoreAboveMapper, 42L));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("true"), fetchSourceValue(ignoreAboveMapper, true));
|
|
||||||
|
|
||||||
KeywordFieldMapper normalizerMapper = new KeywordFieldMapper.Builder("field", createIndexAnalyzers(null)).normalizer("lowercase")
|
|
||||||
.build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("value"), fetchSourceValue(normalizerMapper, "VALUE"));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("42"), fetchSourceValue(normalizerMapper, 42L));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("value"), fetchSourceValue(normalizerMapper, "value"));
|
|
||||||
|
|
||||||
KeywordFieldMapper nullValueMapper = new KeywordFieldMapper.Builder("field")
|
|
||||||
.nullValue("NULL")
|
|
||||||
.build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("NULL"), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.lucene.analysis.TokenFilter;
|
||||||
import org.apache.lucene.analysis.TokenStream;
|
import org.apache.lucene.analysis.TokenStream;
|
||||||
import org.apache.lucene.analysis.Tokenizer;
|
import org.apache.lucene.analysis.Tokenizer;
|
||||||
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
|
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
|
||||||
|
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||||
import org.apache.lucene.document.FieldType;
|
import org.apache.lucene.document.FieldType;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
||||||
|
@ -36,11 +37,20 @@ import org.apache.lucene.search.TermQuery;
|
||||||
import org.apache.lucene.search.TermRangeQuery;
|
import org.apache.lucene.search.TermRangeQuery;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
import org.elasticsearch.common.lucene.BytesRefs;
|
import org.elasticsearch.common.lucene.BytesRefs;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.index.analysis.AnalyzerScope;
|
import org.elasticsearch.index.analysis.AnalyzerScope;
|
||||||
|
import org.elasticsearch.index.analysis.CharFilterFactory;
|
||||||
|
import org.elasticsearch.index.analysis.CustomAnalyzer;
|
||||||
|
import org.elasticsearch.index.analysis.IndexAnalyzers;
|
||||||
|
import org.elasticsearch.index.analysis.LowercaseNormalizer;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
|
import org.elasticsearch.index.analysis.TokenFilterFactory;
|
||||||
|
import org.elasticsearch.index.analysis.TokenizerFactory;
|
||||||
import org.elasticsearch.index.mapper.KeywordFieldMapper.KeywordFieldType;
|
import org.elasticsearch.index.mapper.KeywordFieldMapper.KeywordFieldType;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType.Relation;
|
import org.elasticsearch.index.mapper.MappedFieldType.Relation;
|
||||||
|
|
||||||
|
@ -56,9 +66,9 @@ public class KeywordFieldTypeTests extends FieldTypeTestCase {
|
||||||
KeywordFieldType ft = new KeywordFieldType("field");
|
KeywordFieldType ft = new KeywordFieldType("field");
|
||||||
// current impl ignores args and should always return INTERSECTS
|
// current impl ignores args and should always return INTERSECTS
|
||||||
assertEquals(Relation.INTERSECTS, ft.isFieldWithinQuery(null,
|
assertEquals(Relation.INTERSECTS, ft.isFieldWithinQuery(null,
|
||||||
RandomStrings.randomAsciiOfLengthBetween(random(), 0, 5),
|
RandomStrings.randomAsciiLettersOfLengthBetween(random(), 0, 5),
|
||||||
RandomStrings.randomAsciiOfLengthBetween(random(), 0, 5),
|
RandomStrings.randomAsciiLettersOfLengthBetween(random(), 0, 5),
|
||||||
randomBoolean(), randomBoolean(), null, null, null));
|
randomBoolean(), randomBoolean(), null, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTermQuery() {
|
public void testTermQuery() {
|
||||||
|
@ -110,8 +120,7 @@ public class KeywordFieldTypeTests extends FieldTypeTestCase {
|
||||||
{
|
{
|
||||||
FieldType fieldType = new FieldType();
|
FieldType fieldType = new FieldType();
|
||||||
fieldType.setOmitNorms(false);
|
fieldType.setOmitNorms(false);
|
||||||
KeywordFieldType ft = new KeywordFieldType("field", false, fieldType, randomBoolean(), null, null, null, 1.0f,
|
KeywordFieldType ft = new KeywordFieldType("field", fieldType);
|
||||||
Collections.emptyMap());
|
|
||||||
assertEquals(new NormsFieldExistsQuery("field"), ft.existsQuery(null));
|
assertEquals(new NormsFieldExistsQuery("field"), ft.existsQuery(null));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -170,4 +179,73 @@ public class KeywordFieldTypeTests extends FieldTypeTestCase {
|
||||||
ft = new KeywordFieldType("field", Lucene.STANDARD_ANALYZER);
|
ft = new KeywordFieldType("field", Lucene.STANDARD_ANALYZER);
|
||||||
assertEquals(new TermQuery(new Term("field", new BytesRef("foo"))), ft.termQuery("FOO", null));
|
assertEquals(new TermQuery(new Term("field", new BytesRef("foo"))), ft.termQuery("FOO", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new KeywordFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
assertEquals(Collections.singletonList("value"), fetchSourceValue(mapper, "value"));
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(mapper, 42L));
|
||||||
|
assertEquals(Collections.singletonList("true"), fetchSourceValue(mapper, true));
|
||||||
|
|
||||||
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> fetchSourceValue(mapper, "value", "format"));
|
||||||
|
assertEquals("Field [field] of type [keyword] doesn't support formats.", e.getMessage());
|
||||||
|
|
||||||
|
MappedFieldType ignoreAboveMapper = new KeywordFieldMapper.Builder("field")
|
||||||
|
.ignoreAbove(4)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.emptyList(), fetchSourceValue(ignoreAboveMapper, "value"));
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(ignoreAboveMapper, 42L));
|
||||||
|
assertEquals(Collections.singletonList("true"), fetchSourceValue(ignoreAboveMapper, true));
|
||||||
|
|
||||||
|
MappedFieldType normalizerMapper = new KeywordFieldMapper.Builder("field", createIndexAnalyzers()).normalizer("lowercase")
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList("value"), fetchSourceValue(normalizerMapper, "VALUE"));
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(normalizerMapper, 42L));
|
||||||
|
assertEquals(Collections.singletonList("value"), fetchSourceValue(normalizerMapper, "value"));
|
||||||
|
|
||||||
|
MappedFieldType nullValueMapper = new KeywordFieldMapper.Builder("field")
|
||||||
|
.nullValue("NULL")
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList("NULL"), fetchSourceValue(nullValueMapper, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IndexAnalyzers createIndexAnalyzers() {
|
||||||
|
return new IndexAnalyzers(
|
||||||
|
org.elasticsearch.common.collect.Map.of("default", new NamedAnalyzer("default", AnalyzerScope.INDEX, new StandardAnalyzer())),
|
||||||
|
org.elasticsearch.common.collect.Map.ofEntries(
|
||||||
|
org.elasticsearch.common.collect.Map.entry("lowercase",
|
||||||
|
new NamedAnalyzer("lowercase", AnalyzerScope.INDEX, new LowercaseNormalizer())),
|
||||||
|
org.elasticsearch.common.collect.Map.entry("other_lowercase",
|
||||||
|
new NamedAnalyzer("other_lowercase", AnalyzerScope.INDEX, new LowercaseNormalizer()))
|
||||||
|
),
|
||||||
|
org.elasticsearch.common.collect.Map.of(
|
||||||
|
"lowercase",
|
||||||
|
new NamedAnalyzer(
|
||||||
|
"lowercase",
|
||||||
|
AnalyzerScope.INDEX,
|
||||||
|
new CustomAnalyzer(
|
||||||
|
TokenizerFactory.newFactory("lowercase", WhitespaceTokenizer::new),
|
||||||
|
new CharFilterFactory[0],
|
||||||
|
new TokenFilterFactory[] { new TokenFilterFactory() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "lowercase";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TokenStream create(TokenStream tokenStream) {
|
||||||
|
return new org.apache.lucene.analysis.core.LowerCaseFilter(tokenStream);
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
|
||||||
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
|
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
|
||||||
import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree;
|
import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Explicit;
|
import org.elasticsearch.common.Explicit;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
import org.elasticsearch.common.collect.List;
|
||||||
|
@ -33,7 +31,6 @@ import org.elasticsearch.common.geo.GeoUtils;
|
||||||
import org.elasticsearch.common.geo.ShapeRelation;
|
import org.elasticsearch.common.geo.ShapeRelation;
|
||||||
import org.elasticsearch.common.geo.SpatialStrategy;
|
import org.elasticsearch.common.geo.SpatialStrategy;
|
||||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.geometry.Point;
|
import org.elasticsearch.geometry.Point;
|
||||||
|
@ -43,7 +40,6 @@ import org.elasticsearch.test.TestGeoShapeFieldMapperPlugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
|
@ -635,38 +631,4 @@ public class LegacyGeoShapeFieldMapperTests extends FieldMapperTestCase2<LegacyG
|
||||||
assertThat(fields.length, equalTo(2));
|
assertThat(fields.length, equalTo(2));
|
||||||
assertFieldWarnings("tree", "strategy");
|
assertFieldWarnings("tree", "strategy");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
LegacyGeoShapeFieldMapper mapper = new LegacyGeoShapeFieldMapper.Builder("field").build(context);
|
|
||||||
|
|
||||||
Map<String, Object> jsonLineString = org.elasticsearch.common.collect.Map.of("type", "LineString", "coordinates",
|
|
||||||
List.of(List.of(42.0, 27.1), List.of(30.0, 50.0)));
|
|
||||||
Map<String, Object> jsonPoint = org.elasticsearch.common.collect.Map.of("type", "Point", "coordinates",
|
|
||||||
org.elasticsearch.common.collect.List.of(14.0, 15.0));
|
|
||||||
String wktLineString = "LINESTRING (42.0 27.1, 30.0 50.0)";
|
|
||||||
String wktPoint = "POINT (14.0 15.0)";
|
|
||||||
|
|
||||||
// Test a single shape in geojson format.
|
|
||||||
Object sourceValue = jsonLineString;
|
|
||||||
assertEquals(List.of(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a list of shapes in geojson format.
|
|
||||||
sourceValue = List.of(jsonLineString, jsonPoint);
|
|
||||||
assertEquals(List.of(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a single shape in wkt format.
|
|
||||||
sourceValue = wktLineString;
|
|
||||||
assertEquals(List.of(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
|
|
||||||
// Test a list of shapes in wkt format.
|
|
||||||
sourceValue = List.of(wktLineString, wktPoint);
|
|
||||||
assertEquals(List.of(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
|
||||||
assertEquals(List.of(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,17 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
import org.elasticsearch.common.geo.SpatialStrategy;
|
import org.elasticsearch.common.geo.SpatialStrategy;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper.GeoShapeFieldType;
|
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper.GeoShapeFieldType;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class LegacyGeoShapeFieldTypeTests extends FieldTypeTestCase {
|
public class LegacyGeoShapeFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,4 +43,39 @@ public class LegacyGeoShapeFieldTypeTests extends FieldTypeTestCase {
|
||||||
fieldType.setStrategy(SpatialStrategy.TERM);
|
fieldType.setStrategy(SpatialStrategy.TERM);
|
||||||
assertTrue(fieldType.pointsOnly());
|
assertTrue(fieldType.pointsOnly());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new LegacyGeoShapeFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
|
||||||
|
Map<String, Object> jsonLineString = org.elasticsearch.common.collect.Map.of("type", "LineString", "coordinates",
|
||||||
|
Arrays.asList(Arrays.asList(42.0, 27.1), Arrays.asList(30.0, 50.0)));
|
||||||
|
Map<String, Object> jsonPoint = org.elasticsearch.common.collect.Map.of(
|
||||||
|
"type", "Point",
|
||||||
|
"coordinates", Arrays.asList(14.0, 15.0));
|
||||||
|
String wktLineString = "LINESTRING (42.0 27.1, 30.0 50.0)";
|
||||||
|
String wktPoint = "POINT (14.0 15.0)";
|
||||||
|
|
||||||
|
// Test a single shape in geojson format.
|
||||||
|
Object sourceValue = jsonLineString;
|
||||||
|
assertEquals(Collections.singletonList(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a list of shapes in geojson format.
|
||||||
|
sourceValue = Arrays.asList(jsonLineString, jsonPoint);
|
||||||
|
assertEquals(Arrays.asList(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Arrays.asList(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a single shape in wkt format.
|
||||||
|
sourceValue = wktLineString;
|
||||||
|
assertEquals(Collections.singletonList(jsonLineString), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Collections.singletonList(wktLineString), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
|
||||||
|
// Test a list of shapes in wkt format.
|
||||||
|
sourceValue = Arrays.asList(wktLineString, wktPoint);
|
||||||
|
assertEquals(Arrays.asList(jsonLineString, jsonPoint), fetchSourceValue(mapper, sourceValue, null));
|
||||||
|
assertEquals(Arrays.asList(wktLineString, wktPoint), fetchSourceValue(mapper, sourceValue, "wkt"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,8 @@ package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesArray;
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
|
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
|
||||||
|
@ -229,21 +226,6 @@ public class NumberFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
||||||
assertFalse(dvField.fieldType().stored());
|
assertFalse(dvField.fieldType().stored());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
NumberFieldMapper mapper = new NumberFieldMapper.Builder("field", NumberType.INTEGER, false, true).build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(3), fetchSourceValue(mapper, 3.14));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(42), fetchSourceValue(mapper, "42.9"));
|
|
||||||
|
|
||||||
NumberFieldMapper nullValueMapper = new NumberFieldMapper.Builder("field", NumberType.FLOAT, false, true)
|
|
||||||
.nullValue(2.71f)
|
|
||||||
.build(context);
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(2.71f), fetchSourceValue(nullValueMapper, ""));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of(2.71f), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testOutOfRangeValues() throws IOException {
|
public void testOutOfRangeValues() throws IOException {
|
||||||
final List<OutOfRangeSpec> inputs = Arrays.asList(
|
final List<OutOfRangeSpec> inputs = Arrays.asList(
|
||||||
OutOfRangeSpec.of(NumberType.BYTE, "128", "is out of range for a byte"),
|
OutOfRangeSpec.of(NumberType.BYTE, "128", "is out of range for a byte"),
|
||||||
|
|
|
@ -131,12 +131,15 @@ public class NumberFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertTrue(ft.termQuery(42.1, null) instanceof MatchNoDocsQuery);
|
assertTrue(ft.termQuery(42.1, null) instanceof MatchNoDocsQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MappedFieldType unsearchable() {
|
||||||
|
return new NumberFieldType("field", NumberType.LONG, false, false, true, true, null, Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
public void testTermQuery() {
|
public void testTermQuery() {
|
||||||
MappedFieldType ft = new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG);
|
MappedFieldType ft = new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG);
|
||||||
assertEquals(LongPoint.newExactQuery("field", 42), ft.termQuery("42", null));
|
assertEquals(LongPoint.newExactQuery("field", 42), ft.termQuery("42", null));
|
||||||
|
|
||||||
MappedFieldType unsearchable
|
MappedFieldType unsearchable = unsearchable();
|
||||||
= new NumberFieldType("field", NumberType.LONG, false, false, true, Collections.emptyMap());
|
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.termQuery("42", null));
|
() -> unsearchable.termQuery("42", null));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -253,7 +256,7 @@ public class NumberFieldTypeTests extends FieldTypeTestCase {
|
||||||
SortedNumericDocValuesField.newSlowRangeQuery("field", 1, 3));
|
SortedNumericDocValuesField.newSlowRangeQuery("field", 1, 3));
|
||||||
assertEquals(expected, ft.rangeQuery("1", "3", true, true, null, null, null, MOCK_QSC));
|
assertEquals(expected, ft.rangeQuery("1", "3", true, true, null, null, null, MOCK_QSC));
|
||||||
|
|
||||||
MappedFieldType unsearchable = new NumberFieldType("field", NumberType.LONG, false, false, true, Collections.emptyMap());
|
MappedFieldType unsearchable = unsearchable();
|
||||||
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
() -> unsearchable.rangeQuery("1", "3", true, true, null, null, null, MOCK_QSC));
|
() -> unsearchable.rangeQuery("1", "3", true, true, null, null, null, MOCK_QSC));
|
||||||
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
|
||||||
|
@ -639,4 +642,22 @@ public class NumberFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertThat(NumberType.HALF_FLOAT.parsePoint(bytes), equalTo(value));
|
assertThat(NumberType.HALF_FLOAT.parsePoint(bytes), equalTo(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new NumberFieldMapper.Builder("field", NumberType.INTEGER, false, true)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList(3), fetchSourceValue(mapper, 3.14));
|
||||||
|
assertEquals(Collections.singletonList(42), fetchSourceValue(mapper, "42.9"));
|
||||||
|
|
||||||
|
MappedFieldType nullValueMapper = new NumberFieldMapper.Builder("field", NumberType.FLOAT, false, true)
|
||||||
|
.nullValue(2.71f)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList(2.71f), fetchSourceValue(nullValueMapper, ""));
|
||||||
|
assertEquals(Collections.singletonList(2.71f), fetchSourceValue(nullValueMapper, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.index.mapper.ParametrizedFieldMapper.Parameter;
|
import org.elasticsearch.index.mapper.ParametrizedFieldMapper.Parameter;
|
||||||
import org.elasticsearch.plugins.MapperPlugin;
|
import org.elasticsearch.plugins.MapperPlugin;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -193,11 +192,6 @@ public class ParametrizedMapperTests extends MapperServiceTestCase {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return "test_mapper";
|
return "test_mapper";
|
||||||
|
|
|
@ -22,13 +22,9 @@ package org.elasticsearch.index.mapper;
|
||||||
import org.apache.lucene.document.InetAddressPoint;
|
import org.apache.lucene.document.InetAddressPoint;
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.CheckedConsumer;
|
import org.elasticsearch.common.CheckedConsumer;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.network.InetAddresses;
|
import org.elasticsearch.common.network.InetAddresses;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
@ -36,7 +32,6 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.RangeQueryBuilder.GTE_FIELD;
|
import static org.elasticsearch.index.query.RangeQueryBuilder.GTE_FIELD;
|
||||||
|
@ -367,39 +362,4 @@ public class RangeFieldMapperTests extends AbstractNumericFieldMapperTestCase {
|
||||||
assertThat(e.getMessage(), containsString("Invalid format: [[test_format]]: Unknown pattern letter: t"));
|
assertThat(e.getMessage(), containsString("Invalid format: [[test_format]]: Unknown pattern letter: t"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
RangeFieldMapper longMapper = new RangeFieldMapper.Builder("field", RangeType.LONG, true).build(context);
|
|
||||||
Map<String, Object> longRange = org.elasticsearch.common.collect.Map.of("gte", 3.14, "lt", "42.9");
|
|
||||||
assertEquals(List.of(org.elasticsearch.common.collect.Map.of("gte", 3L, "lt", 42L)),
|
|
||||||
fetchSourceValue(longMapper, longRange));
|
|
||||||
|
|
||||||
RangeFieldMapper dateMapper = new RangeFieldMapper.Builder("field", RangeType.DATE, true)
|
|
||||||
.format("yyyy/MM/dd||epoch_millis")
|
|
||||||
.build(context);
|
|
||||||
Map<String, Object> dateRange = org.elasticsearch.common.collect.Map.of("lt", "1990/12/29", "gte", 597429487111L);
|
|
||||||
assertEquals(List.of(org.elasticsearch.common.collect.Map.of("lt", "1990/12/29", "gte", "1988/12/06")),
|
|
||||||
fetchSourceValue(dateMapper, dateRange));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testParseSourceValueWithFormat() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
RangeFieldMapper longMapper = new RangeFieldMapper.Builder("field", RangeType.LONG, true).build(context);
|
|
||||||
Map<String, Object> longRange = org.elasticsearch.common.collect.Map.of("gte", 3.14, "lt", "42.9");
|
|
||||||
assertEquals(List.of(org.elasticsearch.common.collect.Map.of("gte", 3L, "lt", 42L)),
|
|
||||||
fetchSourceValue(longMapper, longRange));
|
|
||||||
|
|
||||||
RangeFieldMapper dateMapper = new RangeFieldMapper.Builder("field", RangeType.DATE, true)
|
|
||||||
.format("strict_date_time")
|
|
||||||
.build(context);
|
|
||||||
Map<String, Object> dateRange = org.elasticsearch.common.collect.Map.of("lt", "1990-12-29T00:00:00.000Z");
|
|
||||||
assertEquals(List.of(org.elasticsearch.common.collect.Map.of("lt", "1990/12/29")),
|
|
||||||
fetchSourceValue(dateMapper, dateRange, "yyy/MM/dd"));
|
|
||||||
assertEquals(List.of(org.elasticsearch.common.collect.Map.of("lt", "662428800000")),
|
|
||||||
fetchSourceValue(dateMapper, dateRange,"epoch_millis"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,10 @@ import org.elasticsearch.test.IndexSettingsModule;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
@ -66,9 +68,9 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
private RangeFieldType createDefaultFieldType() {
|
private RangeFieldType createDefaultFieldType() {
|
||||||
if (type == RangeType.DATE) {
|
if (type == RangeType.DATE) {
|
||||||
return new RangeFieldType("field", true, false, true, RangeFieldMapper.Defaults.DATE_FORMATTER, Collections.emptyMap());
|
return new RangeFieldType("field", RangeFieldMapper.Defaults.DATE_FORMATTER);
|
||||||
}
|
}
|
||||||
return new RangeFieldType("field", type, true, false, true, Collections.emptyMap());
|
return new RangeFieldType("field", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRangeQuery() throws Exception {
|
public void testRangeQuery() throws Exception {
|
||||||
|
@ -216,8 +218,7 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
public void testDateRangeQueryUsingMappingFormat() {
|
public void testDateRangeQueryUsingMappingFormat() {
|
||||||
QueryShardContext context = createContext();
|
QueryShardContext context = createContext();
|
||||||
RangeFieldType strict
|
RangeFieldType strict = new RangeFieldType("field", RangeFieldMapper.Defaults.DATE_FORMATTER);
|
||||||
= new RangeFieldType("field", true, false, false, RangeFieldMapper.Defaults.DATE_FORMATTER, Collections.emptyMap());
|
|
||||||
// don't use DISJOINT here because it doesn't work on date fields which we want to compare bounds with
|
// don't use DISJOINT here because it doesn't work on date fields which we want to compare bounds with
|
||||||
ShapeRelation relation = randomValueOtherThan(ShapeRelation.DISJOINT,() -> randomFrom(ShapeRelation.values()));
|
ShapeRelation relation = randomValueOtherThan(ShapeRelation.DISJOINT,() -> randomFrom(ShapeRelation.values()));
|
||||||
|
|
||||||
|
@ -236,13 +237,13 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertEquals(1465975790000L, formatter.parseMillis(from));
|
assertEquals(1465975790000L, formatter.parseMillis(from));
|
||||||
assertEquals(1466062190000L, formatter.parseMillis(to));
|
assertEquals(1466062190000L, formatter.parseMillis(to));
|
||||||
|
|
||||||
RangeFieldType fieldType = new RangeFieldType("field", true, false, true, formatter, Collections.emptyMap());
|
RangeFieldType fieldType = new RangeFieldType("field", formatter);
|
||||||
final Query query = fieldType.rangeQuery(from, to, true, true, relation, null, fieldType.dateMathParser(), context);
|
final Query query = fieldType.rangeQuery(from, to, true, true, relation, null, fieldType.dateMathParser(), context);
|
||||||
assertEquals("field:<ranges:[1465975790000 : 1466062190999]>", query.toString());
|
assertEquals("field:<ranges:[1465975790000 : 1466062190999]>", query.toString());
|
||||||
|
|
||||||
// compare lower and upper bounds with what we would get on a `date` field
|
// compare lower and upper bounds with what we would get on a `date` field
|
||||||
DateFieldType dateFieldType
|
DateFieldType dateFieldType
|
||||||
= new DateFieldType("field", true, false, true, formatter, DateFieldMapper.Resolution.MILLISECONDS, Collections.emptyMap());
|
= new DateFieldType("field", DateFieldMapper.Resolution.MILLISECONDS, formatter);
|
||||||
final Query queryOnDateField = dateFieldType.rangeQuery(from, to, true, true, relation, null, fieldType.dateMathParser(), context);
|
final Query queryOnDateField = dateFieldType.rangeQuery(from, to, true, true, relation, null, fieldType.dateMathParser(), context);
|
||||||
assertEquals("field:[1465975790000 TO 1466062190999]", queryOnDateField.toString());
|
assertEquals("field:[1465975790000 TO 1466062190999]", queryOnDateField.toString());
|
||||||
}
|
}
|
||||||
|
@ -259,7 +260,7 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
long lower = randomLongBetween(formatter.parseMillis("2000-01-01T00:00"), formatter.parseMillis("2010-01-01T00:00"));
|
long lower = randomLongBetween(formatter.parseMillis("2000-01-01T00:00"), formatter.parseMillis("2010-01-01T00:00"));
|
||||||
long upper = randomLongBetween(formatter.parseMillis("2011-01-01T00:00"), formatter.parseMillis("2020-01-01T00:00"));
|
long upper = randomLongBetween(formatter.parseMillis("2011-01-01T00:00"), formatter.parseMillis("2020-01-01T00:00"));
|
||||||
|
|
||||||
RangeFieldType fieldType = new RangeFieldType("field", true, false, false, formatter, Collections.emptyMap());
|
RangeFieldType fieldType = new RangeFieldType("field", true, false, false, formatter, false, null);
|
||||||
String lowerAsString = formatter.formatMillis(lower);
|
String lowerAsString = formatter.formatMillis(lower);
|
||||||
String upperAsString = formatter.formatMillis(upper);
|
String upperAsString = formatter.formatMillis(upper);
|
||||||
// also add date math rounding to days occasionally
|
// also add date math rounding to days occasionally
|
||||||
|
@ -481,7 +482,7 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertEquals(getExpectedRangeQuery(relation, value, value, includeLower, includeUpper),
|
assertEquals(getExpectedRangeQuery(relation, value, value, includeLower, includeUpper),
|
||||||
ft.termQuery(value, context));
|
ft.termQuery(value, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCaseInsensitiveQuery() throws Exception {
|
public void testCaseInsensitiveQuery() throws Exception {
|
||||||
QueryShardContext context = createContext();
|
QueryShardContext context = createContext();
|
||||||
RangeFieldType ft = createDefaultFieldType();
|
RangeFieldType ft = createDefaultFieldType();
|
||||||
|
@ -491,4 +492,46 @@ public class RangeFieldTypeTests extends FieldTypeTestCase {
|
||||||
() -> ft.termQueryCaseInsensitive(value, context));
|
() -> ft.termQueryCaseInsensitive(value, context));
|
||||||
assertTrue(ex.getMessage().contains("does not support case insensitive term queries"));
|
assertTrue(ex.getMessage().contains("does not support case insensitive term queries"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType longMapper = new RangeFieldMapper.Builder("field", RangeType.LONG, true)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
Map<String, Object> longRange = org.elasticsearch.common.collect.Map.of("gte", 3.14, "lt", "42.9");
|
||||||
|
assertEquals(Collections.singletonList(org.elasticsearch.common.collect.Map.of("gte", 3L, "lt", 42L)),
|
||||||
|
fetchSourceValue(longMapper, longRange));
|
||||||
|
|
||||||
|
MappedFieldType dateMapper = new RangeFieldMapper.Builder("field", RangeType.DATE, true)
|
||||||
|
.format("yyyy/MM/dd||epoch_millis")
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
Map<String, Object> dateRange = org.elasticsearch.common.collect.Map.of("lt", "1990/12/29", "gte", 597429487111L);
|
||||||
|
assertEquals(Collections.singletonList(org.elasticsearch.common.collect.Map.of("lt", "1990/12/29", "gte", "1988/12/06")),
|
||||||
|
fetchSourceValue(dateMapper, dateRange));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParseSourceValueWithFormat() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType longMapper = new RangeFieldMapper.Builder("field", RangeType.LONG, true)
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
Map<String, Object> longRange = org.elasticsearch.common.collect.Map.of("gte", 3.14, "lt", "42.9");
|
||||||
|
assertEquals(Collections.singletonList(org.elasticsearch.common.collect.Map.of("gte", 3L, "lt", 42L)),
|
||||||
|
fetchSourceValue(longMapper, longRange));
|
||||||
|
|
||||||
|
MappedFieldType dateMapper = new RangeFieldMapper.Builder("field", RangeType.DATE, true)
|
||||||
|
.format("strict_date_time")
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
Map<String, Object> dateRange = org.elasticsearch.common.collect.Map.of("lt", "1990-12-29T00:00:00.000Z");
|
||||||
|
assertEquals(Collections.singletonList(org.elasticsearch.common.collect.Map.of("lt", "1990/12/29")),
|
||||||
|
fetchSourceValue(dateMapper, dateRange, "yyy/MM/dd"));
|
||||||
|
assertEquals(Collections.singletonList(org.elasticsearch.common.collect.Map.of("lt", "662428800000")),
|
||||||
|
fetchSourceValue(dateMapper, dateRange,"epoch_millis"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,8 @@ import org.apache.lucene.search.spans.SpanNearQuery;
|
||||||
import org.apache.lucene.search.spans.SpanOrQuery;
|
import org.apache.lucene.search.spans.SpanOrQuery;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
|
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
@ -993,16 +990,4 @@ public class TextFieldMapperTests extends FieldMapperTestCase2<TextFieldMapper.B
|
||||||
assertThat(mapperService.documentMapper().mappers().getMapper("field"), instanceOf(TextFieldMapper.class));
|
assertThat(mapperService.documentMapper().mappers().getMapper("field"), instanceOf(TextFieldMapper.class));
|
||||||
assertThat(mapperService.documentMapper().mappers().getMapper("other_field"), instanceOf(KeywordFieldMapper.class));
|
assertThat(mapperService.documentMapper().mappers().getMapper("other_field"), instanceOf(KeywordFieldMapper.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
FieldMapper fieldMapper = newBuilder().build(context);
|
|
||||||
TextFieldMapper mapper = (TextFieldMapper) fieldMapper;
|
|
||||||
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("value"), fetchSourceValue(mapper, "value"));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("42"), fetchSourceValue(mapper, 42L));
|
|
||||||
assertEquals(org.elasticsearch.common.collect.List.of("true"), fetchSourceValue(mapper, true));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,15 @@ import org.apache.lucene.util.automaton.Automata;
|
||||||
import org.apache.lucene.util.automaton.Automaton;
|
import org.apache.lucene.util.automaton.Automaton;
|
||||||
import org.apache.lucene.util.automaton.Operations;
|
import org.apache.lucene.util.automaton.Operations;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
import org.elasticsearch.common.lucene.BytesRefs;
|
import org.elasticsearch.common.lucene.BytesRefs;
|
||||||
import org.elasticsearch.common.lucene.search.AutomatonQueries;
|
import org.elasticsearch.common.lucene.search.AutomatonQueries;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType;
|
import org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -160,4 +164,15 @@ public class TextFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
assertThat(q, equalTo(expected));
|
assertThat(q, equalTo(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
MappedFieldType mapper = new TextFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
|
||||||
|
assertEquals(Collections.singletonList("value"), fetchSourceValue(mapper, "value"));
|
||||||
|
assertEquals(Collections.singletonList("42"), fetchSourceValue(mapper, 42L));
|
||||||
|
assertEquals(Collections.singletonList("true"), fetchSourceValue(mapper, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,8 @@ public class AggregatorBaseTests extends ESSingleNodeTestCase {
|
||||||
boolean indexed,
|
boolean indexed,
|
||||||
QueryShardContext context
|
QueryShardContext context
|
||||||
) {
|
) {
|
||||||
MappedFieldType ft = new NumberFieldMapper.NumberFieldType(fieldName, numType, indexed, false, true, Collections.emptyMap());
|
MappedFieldType ft
|
||||||
|
= new NumberFieldMapper.NumberFieldType(fieldName, numType, indexed, false, true, false, null, Collections.emptyMap());
|
||||||
return ValuesSourceConfig.resolveFieldOnly(ft, context);
|
return ValuesSourceConfig.resolveFieldOnly(ft, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ public class AggregatorBaseTests extends ESSingleNodeTestCase {
|
||||||
QueryShardContext context
|
QueryShardContext context
|
||||||
) {
|
) {
|
||||||
MappedFieldType ft = new DateFieldMapper.DateFieldType(fieldName, indexed, false, true,
|
MappedFieldType ft = new DateFieldMapper.DateFieldType(fieldName, indexed, false, true,
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, resolution, Collections.emptyMap());
|
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, resolution, null, Collections.emptyMap());
|
||||||
return ValuesSourceConfig.resolveFieldOnly(ft, context);
|
return ValuesSourceConfig.resolveFieldOnly(ft, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,6 @@ public abstract class DateHistogramAggregatorTestCase extends AggregatorTestCase
|
||||||
return new DateFieldMapper.DateFieldType(AGGREGABLE_DATE, isSearchable, false, true,
|
return new DateFieldMapper.DateFieldType(AGGREGABLE_DATE, isSearchable, false, true,
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
||||||
useNanosecondResolution ? DateFieldMapper.Resolution.NANOSECONDS : DateFieldMapper.Resolution.MILLISECONDS,
|
useNanosecondResolution ? DateFieldMapper.Resolution.NANOSECONDS : DateFieldMapper.Resolution.MILLISECONDS,
|
||||||
Collections.emptyMap());
|
null, Collections.emptyMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,7 +272,7 @@ public class DateRangeAggregatorTests extends AggregatorTestCase {
|
||||||
Consumer<InternalRange<? extends InternalRange.Bucket, ? extends InternalRange>> verify,
|
Consumer<InternalRange<? extends InternalRange.Bucket, ? extends InternalRange>> verify,
|
||||||
DateFieldMapper.Resolution resolution) throws IOException {
|
DateFieldMapper.Resolution resolution) throws IOException {
|
||||||
DateFieldMapper.DateFieldType fieldType = new DateFieldMapper.DateFieldType(DATE_FIELD_NAME, true, false, true,
|
DateFieldMapper.DateFieldType fieldType = new DateFieldMapper.DateFieldType(DATE_FIELD_NAME, true, false, true,
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, resolution, Collections.emptyMap());
|
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, resolution, null, Collections.emptyMap());
|
||||||
DateRangeAggregationBuilder aggregationBuilder = new DateRangeAggregationBuilder("test_range_agg");
|
DateRangeAggregationBuilder aggregationBuilder = new DateRangeAggregationBuilder("test_range_agg");
|
||||||
aggregationBuilder.field(DATE_FIELD_NAME);
|
aggregationBuilder.field(DATE_FIELD_NAME);
|
||||||
aggregationBuilder.addRange("2015-01-01", "2015-12-31");
|
aggregationBuilder.addRange("2015-01-01", "2015-12-31");
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class RangeAggregatorTests extends AggregatorTestCase {
|
||||||
@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/57651")
|
@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/57651")
|
||||||
public void testDateFieldNanosecondResolution() throws IOException {
|
public void testDateFieldNanosecondResolution() throws IOException {
|
||||||
DateFieldMapper.DateFieldType fieldType = new DateFieldMapper.DateFieldType(DATE_FIELD_NAME, true, false, true,
|
DateFieldMapper.DateFieldType fieldType = new DateFieldMapper.DateFieldType(DATE_FIELD_NAME, true, false, true,
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, DateFieldMapper.Resolution.NANOSECONDS, Collections.emptyMap());
|
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, DateFieldMapper.Resolution.NANOSECONDS, null, Collections.emptyMap());
|
||||||
|
|
||||||
// These values should work because aggs scale nanosecond up to millisecond always.
|
// These values should work because aggs scale nanosecond up to millisecond always.
|
||||||
long milli1 = ZonedDateTime.of(2015, 11, 13, 16, 14, 34, 0, ZoneOffset.UTC).toInstant().toEpochMilli();
|
long milli1 = ZonedDateTime.of(2015, 11, 13, 16, 14, 34, 0, ZoneOffset.UTC).toInstant().toEpochMilli();
|
||||||
|
@ -144,7 +144,7 @@ public class RangeAggregatorTests extends AggregatorTestCase {
|
||||||
@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/57651")
|
@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/57651")
|
||||||
public void testMissingDateWithDateField() throws IOException {
|
public void testMissingDateWithDateField() throws IOException {
|
||||||
DateFieldMapper.DateFieldType fieldType = new DateFieldMapper.DateFieldType(DATE_FIELD_NAME, true, false, true,
|
DateFieldMapper.DateFieldType fieldType = new DateFieldMapper.DateFieldType(DATE_FIELD_NAME, true, false, true,
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, DateFieldMapper.Resolution.NANOSECONDS, Collections.emptyMap());
|
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, DateFieldMapper.Resolution.NANOSECONDS, null, Collections.emptyMap());
|
||||||
|
|
||||||
// These values should work because aggs scale nanosecond up to millisecond always.
|
// These values should work because aggs scale nanosecond up to millisecond always.
|
||||||
long milli1 = ZonedDateTime.of(2015, 11, 13, 16, 14, 34, 0, ZoneOffset.UTC).toInstant().toEpochMilli();
|
long milli1 = ZonedDateTime.of(2015, 11, 13, 16, 14, 34, 0, ZoneOffset.UTC).toInstant().toEpochMilli();
|
||||||
|
|
|
@ -32,12 +32,15 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.mapper.KeywordFieldMapper;
|
import org.elasticsearch.index.mapper.KeywordFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
import org.elasticsearch.index.mapper.NumberFieldMapper;
|
import org.elasticsearch.index.mapper.NumberFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.TextSearchInfo;
|
import org.elasticsearch.index.mapper.TextSearchInfo;
|
||||||
|
import org.elasticsearch.index.mapper.ValueFetcher;
|
||||||
import org.elasticsearch.index.query.InnerHitBuilder;
|
import org.elasticsearch.index.query.InnerHitBuilder;
|
||||||
import org.elasticsearch.index.query.InnerHitBuilderTests;
|
import org.elasticsearch.index.query.InnerHitBuilderTests;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.search.SearchModule;
|
import org.elasticsearch.search.SearchModule;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -155,14 +158,14 @@ public class CollapseBuilderTests extends AbstractSerializingTestCase<CollapseBu
|
||||||
|
|
||||||
numberFieldType =
|
numberFieldType =
|
||||||
new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG, true, false,
|
new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG, true, false,
|
||||||
false, Collections.emptyMap());
|
false, false, null, Collections.emptyMap());
|
||||||
when(shardContext.fieldMapper("field")).thenReturn(numberFieldType);
|
when(shardContext.fieldMapper("field")).thenReturn(numberFieldType);
|
||||||
IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> builder.build(shardContext));
|
IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> builder.build(shardContext));
|
||||||
assertEquals(exc.getMessage(), "cannot collapse on field `field` without `doc_values`");
|
assertEquals(exc.getMessage(), "cannot collapse on field `field` without `doc_values`");
|
||||||
|
|
||||||
numberFieldType =
|
numberFieldType =
|
||||||
new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG, false, false,
|
new NumberFieldMapper.NumberFieldType("field", NumberFieldMapper.NumberType.LONG, false, false,
|
||||||
true, Collections.emptyMap());
|
true, false, null, Collections.emptyMap());
|
||||||
when(shardContext.fieldMapper("field")).thenReturn(numberFieldType);
|
when(shardContext.fieldMapper("field")).thenReturn(numberFieldType);
|
||||||
builder.setInnerHits(new InnerHitBuilder());
|
builder.setInnerHits(new InnerHitBuilder());
|
||||||
exc = expectThrows(IllegalArgumentException.class, () -> builder.build(shardContext));
|
exc = expectThrows(IllegalArgumentException.class, () -> builder.build(shardContext));
|
||||||
|
@ -205,6 +208,11 @@ public class CollapseBuilderTests extends AbstractSerializingTestCase<CollapseBu
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query termQuery(Object value, QueryShardContext context) {
|
public Query termQuery(Object value, QueryShardContext context) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -52,10 +52,13 @@ import org.elasticsearch.index.IndexSettings;
|
||||||
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
|
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
|
||||||
import org.elasticsearch.index.mapper.IdFieldMapper;
|
import org.elasticsearch.index.mapper.IdFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
import org.elasticsearch.index.mapper.TextSearchInfo;
|
import org.elasticsearch.index.mapper.TextSearchInfo;
|
||||||
|
import org.elasticsearch.index.mapper.ValueFetcher;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.index.shard.ShardId;
|
import org.elasticsearch.index.shard.ShardId;
|
||||||
import org.elasticsearch.search.internal.ShardSearchRequest;
|
import org.elasticsearch.search.internal.ShardSearchRequest;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -122,6 +125,11 @@ public class SliceBuilderTests extends ESTestCase {
|
||||||
MappedFieldType fieldType = new MappedFieldType(fieldName, true, false, dvType != null,
|
MappedFieldType fieldType = new MappedFieldType(fieldName, true, false, dvType != null,
|
||||||
TextSearchInfo.NONE, Collections.emptyMap()) {
|
TextSearchInfo.NONE, Collections.emptyMap()) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||||
import org.elasticsearch.index.IndexService;
|
import org.elasticsearch.index.IndexService;
|
||||||
import org.elasticsearch.index.analysis.AnalyzerScope;
|
import org.elasticsearch.index.analysis.AnalyzerScope;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
|
||||||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -45,8 +44,6 @@ import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for testing {@link FieldMapper}s.
|
* Base class for testing {@link FieldMapper}s.
|
||||||
|
@ -253,21 +250,4 @@ public abstract class FieldMapperTestCase<T extends FieldMapper.Builder<?>> exte
|
||||||
x.endObject().endObject();
|
x.endObject().endObject();
|
||||||
return Strings.toString(x);
|
return Strings.toString(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<?> fetchSourceValue(FieldMapper mapper, Object sourceValue) throws IOException {
|
|
||||||
return fetchSourceValue(mapper, sourceValue, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<?> fetchSourceValue(FieldMapper mapper, Object sourceValue, String format) throws IOException {
|
|
||||||
String field = mapper.name();
|
|
||||||
|
|
||||||
MapperService mapperService = mock(MapperService.class);
|
|
||||||
when(mapperService.sourcePath(field)).thenReturn(org.elasticsearch.common.collect.Set.of(field));
|
|
||||||
|
|
||||||
ValueFetcher fetcher = mapper.valueFetcher(mapperService, null, format);
|
|
||||||
SourceLookup lookup = new SourceLookup();
|
|
||||||
lookup.setSource(Collections.singletonMap(field, sourceValue));
|
|
||||||
return fetcher.fetchValues(lookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,13 @@
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
import org.elasticsearch.search.lookup.SourceLookup;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ -39,4 +44,21 @@ public abstract class FieldTypeTestCase extends ESTestCase {
|
||||||
when(queryShardContext.allowExpensiveQueries()).thenReturn(allowExpensiveQueries);
|
when(queryShardContext.allowExpensiveQueries()).thenReturn(allowExpensiveQueries);
|
||||||
return queryShardContext;
|
return queryShardContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<?> fetchSourceValue(MappedFieldType fieldType, Object sourceValue) throws IOException {
|
||||||
|
return fetchSourceValue(fieldType, sourceValue, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<?> fetchSourceValue(MappedFieldType fieldType, Object sourceValue, String format) throws IOException {
|
||||||
|
String field = fieldType.name();
|
||||||
|
|
||||||
|
MapperService mapperService = mock(MapperService.class);
|
||||||
|
when(mapperService.sourcePath(field)).thenReturn(org.elasticsearch.common.collect.Set.of(field));
|
||||||
|
|
||||||
|
ValueFetcher fetcher = fieldType.valueFetcher(mapperService, null, format);
|
||||||
|
SourceLookup lookup = new SourceLookup();
|
||||||
|
lookup.setSource(Collections.singletonMap(field, sourceValue));
|
||||||
|
return fetcher.fetchValues(lookup);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
|
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
|
||||||
import org.elasticsearch.search.DocValueFormat;
|
import org.elasticsearch.search.DocValueFormat;
|
||||||
import org.elasticsearch.search.lookup.SearchLookup;
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -58,8 +57,6 @@ import java.util.function.Supplier;
|
||||||
import static org.hamcrest.Matchers.anyOf;
|
import static org.hamcrest.Matchers.anyOf;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for testing {@link Mapper}s.
|
* Base class for testing {@link Mapper}s.
|
||||||
|
@ -265,24 +262,8 @@ public abstract class MapperTestCase extends MapperServiceTestCase {
|
||||||
assertParseMinimalWarnings();
|
assertParseMinimalWarnings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<?> fetchSourceValue(FieldMapper mapper, Object sourceValue) throws IOException {
|
|
||||||
return fetchSourceValue(mapper, sourceValue, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<?> fetchSourceValue(FieldMapper mapper, Object sourceValue, String format) throws IOException {
|
|
||||||
String field = mapper.name();
|
|
||||||
|
|
||||||
MapperService mapperService = mock(MapperService.class);
|
|
||||||
when(mapperService.sourcePath(field)).thenReturn(org.elasticsearch.common.collect.Set.of(field));
|
|
||||||
|
|
||||||
ValueFetcher fetcher = mapper.valueFetcher(mapperService, null, format);
|
|
||||||
SourceLookup lookup = new SourceLookup();
|
|
||||||
lookup.setSource(Collections.singletonMap(field, sourceValue));
|
|
||||||
return fetcher.fetchValues(lookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use a {@linkplain FieldMapper} to extract values from doc values.
|
* Use a {@linkplain ValueFetcher} to extract values from doc values.
|
||||||
*/
|
*/
|
||||||
protected final List<?> fetchFromDocValues(MapperService mapperService, MappedFieldType ft, DocValueFormat format, Object sourceValue)
|
protected final List<?> fetchFromDocValues(MapperService mapperService, MappedFieldType ft, DocValueFormat format, Object sourceValue)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
|
@ -68,6 +68,11 @@ public class MockFieldMapper extends ParametrizedFieldMapper {
|
||||||
public String typeName() {
|
public String typeName() {
|
||||||
return "faketype";
|
return "faketype";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,11 +84,6 @@ public class MockFieldMapper extends ParametrizedFieldMapper {
|
||||||
protected void parseCreateField(ParseContext context) {
|
protected void parseCreateField(ParseContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder extends ParametrizedFieldMapper.Builder {
|
public static class Builder extends ParametrizedFieldMapper.Builder {
|
||||||
private final MappedFieldType fieldType;
|
private final MappedFieldType fieldType;
|
||||||
|
|
||||||
|
|
|
@ -125,19 +125,6 @@ public class HistogramFieldMapper extends ParametrizedFieldMapper {
|
||||||
throw new UnsupportedOperationException("Parsing is implemented in parse(), this method should NEVER be called");
|
throw new UnsupportedOperationException("Parsing is implemented in parse(), this method should NEVER be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue()) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HistogramFieldType extends MappedFieldType {
|
public static class HistogramFieldType extends MappedFieldType {
|
||||||
|
|
||||||
public HistogramFieldType(String name, Map<String, String> meta) {
|
public HistogramFieldType(String name, Map<String, String> meta) {
|
||||||
|
@ -149,6 +136,19 @@ public class HistogramFieldMapper extends ParametrizedFieldMapper {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, Supplier<SearchLookup> searchLookup) {
|
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, Supplier<SearchLookup> searchLookup) {
|
||||||
failIfNoDocValues();
|
failIfNoDocValues();
|
||||||
|
|
|
@ -432,6 +432,7 @@ public class RateAggregatorTests extends AggregatorTestCase {
|
||||||
true,
|
true,
|
||||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
||||||
DateFieldMapper.Resolution.MILLISECONDS,
|
DateFieldMapper.Resolution.MILLISECONDS,
|
||||||
|
null,
|
||||||
Collections.emptyMap()
|
Collections.emptyMap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,15 @@ import org.elasticsearch.index.mapper.DateFieldMapper;
|
||||||
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.MapperService;
|
||||||
import org.elasticsearch.index.mapper.MappingLookup;
|
import org.elasticsearch.index.mapper.MappingLookup;
|
||||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||||
import org.elasticsearch.index.mapper.ParametrizedFieldMapper;
|
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.mapper.ValueFetcher;
|
||||||
import org.elasticsearch.index.query.QueryShardContext;
|
import org.elasticsearch.index.query.QueryShardContext;
|
||||||
|
import org.elasticsearch.search.lookup.SearchLookup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
|
@ -60,6 +63,11 @@ public class DataStreamTimestampFieldMapper extends MetadataFieldMapper {
|
||||||
public Query existsQuery(QueryShardContext context) {
|
public Query existsQuery(QueryShardContext context) {
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] does not support exists queries");
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] does not support exists queries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DataStreamTimestampFieldMapper toType(FieldMapper in) {
|
private static DataStreamTimestampFieldMapper toType(FieldMapper in) {
|
||||||
|
|
|
@ -9,11 +9,9 @@ package org.elasticsearch.xpack.constantkeyword.mapper;
|
||||||
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.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.compress.CompressedXContent;
|
import org.elasticsearch.common.compress.CompressedXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||||
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.MapperParsingException;
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
|
@ -21,18 +19,14 @@ import org.elasticsearch.index.mapper.MapperService.MergeReason;
|
||||||
import org.elasticsearch.index.mapper.MapperTestCase;
|
import org.elasticsearch.index.mapper.MapperTestCase;
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||||
import org.elasticsearch.index.mapper.ValueFetcher;
|
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.search.lookup.SourceLookup;
|
|
||||||
import org.elasticsearch.xpack.constantkeyword.ConstantKeywordMapperPlugin;
|
import org.elasticsearch.xpack.constantkeyword.ConstantKeywordMapperPlugin;
|
||||||
import org.elasticsearch.xpack.constantkeyword.mapper.ConstantKeywordFieldMapper.ConstantKeywordFieldType;
|
import org.elasticsearch.xpack.constantkeyword.mapper.ConstantKeywordFieldMapper.ConstantKeywordFieldType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import static java.util.Collections.singleton;
|
import static java.util.Collections.singleton;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
|
||||||
public class ConstantKeywordFieldMapperTests extends MapperTestCase {
|
public class ConstantKeywordFieldMapperTests extends MapperTestCase {
|
||||||
|
@ -162,24 +156,4 @@ public class ConstantKeywordFieldMapperTests extends MapperTestCase {
|
||||||
b.field("value", "bar");
|
b.field("value", "bar");
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchValue() throws Exception {
|
|
||||||
MapperService mapperService = createMapperService(fieldMapping(b -> b.field("type", "constant_keyword")));
|
|
||||||
FieldMapper fieldMapper = (FieldMapper) mapperService.documentMapper().mappers().getMapper("field");
|
|
||||||
ValueFetcher fetcher = fieldMapper.valueFetcher(mapperService, null, null);
|
|
||||||
|
|
||||||
SourceLookup missingValueLookup = new SourceLookup();
|
|
||||||
SourceLookup nullValueLookup = new SourceLookup();
|
|
||||||
nullValueLookup.setSource(Collections.singletonMap("field", null));
|
|
||||||
|
|
||||||
assertTrue(fetcher.fetchValues(missingValueLookup).isEmpty());
|
|
||||||
assertTrue(fetcher.fetchValues(nullValueLookup).isEmpty());
|
|
||||||
|
|
||||||
merge(mapperService, fieldMapping(b -> b.field("type", "constant_keyword").field("value", "foo")));
|
|
||||||
fieldMapper = (FieldMapper) mapperService.documentMapper().mappers().getMapper("field");
|
|
||||||
fetcher = fieldMapper.valueFetcher(mapperService, null, null);
|
|
||||||
|
|
||||||
assertEquals(List.of("foo"), fetcher.fetchValues(missingValueLookup));
|
|
||||||
assertEquals(List.of("foo"), fetcher.fetchValues(nullValueLookup));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,17 @@ public class ConstantKeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
return new ConstantIndexFieldData.Builder(mapperService -> value, name(), CoreValuesSourceType.BYTES);
|
return new ConstantIndexFieldData.Builder(mapperService -> value, name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value == null
|
||||||
|
? lookup -> Collections.emptyList()
|
||||||
|
: lookup -> Collections.singletonList(value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean matches(String pattern, boolean caseInsensitive, QueryShardContext context) {
|
protected boolean matches(String pattern, boolean caseInsensitive, QueryShardContext context) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
@ -251,17 +262,6 @@ public class ConstantKeywordFieldMapper extends ParametrizedFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return fieldType().value == null
|
|
||||||
? lookup -> org.elasticsearch.common.collect.List.of()
|
|
||||||
: lookup -> org.elasticsearch.common.collect.List.of(fieldType().value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String contentType() {
|
protected String contentType() {
|
||||||
return CONTENT_TYPE;
|
return CONTENT_TYPE;
|
||||||
|
|
|
@ -11,6 +11,9 @@ import org.apache.lucene.search.MatchNoDocsQuery;
|
||||||
import org.apache.lucene.util.automaton.RegExp;
|
import org.apache.lucene.util.automaton.RegExp;
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.index.mapper.FieldTypeTestCase;
|
import org.elasticsearch.index.mapper.FieldTypeTestCase;
|
||||||
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
|
import org.elasticsearch.index.mapper.ValueFetcher;
|
||||||
|
import org.elasticsearch.search.lookup.SourceLookup;
|
||||||
import org.elasticsearch.xpack.constantkeyword.mapper.ConstantKeywordFieldMapper.ConstantKeywordFieldType;
|
import org.elasticsearch.xpack.constantkeyword.mapper.ConstantKeywordFieldMapper.ConstantKeywordFieldType;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -100,4 +103,22 @@ public class ConstantKeywordFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertEquals(new MatchAllDocsQuery(), ft.regexpQuery("f.o", RegExp.ALL, 0, 10, null, null));
|
assertEquals(new MatchAllDocsQuery(), ft.regexpQuery("f.o", RegExp.ALL, 0, 10, null, null));
|
||||||
assertEquals(new MatchNoDocsQuery(), ft.regexpQuery("f..o", RegExp.ALL, 0, 10, null, null));
|
assertEquals(new MatchNoDocsQuery(), ft.regexpQuery("f..o", RegExp.ALL, 0, 10, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFetchValue() throws Exception {
|
||||||
|
MappedFieldType fieldType = new ConstantKeywordFieldMapper.ConstantKeywordFieldType("field", null);
|
||||||
|
ValueFetcher fetcher = fieldType.valueFetcher(null, null, null);
|
||||||
|
|
||||||
|
SourceLookup missingValueLookup = new SourceLookup();
|
||||||
|
SourceLookup nullValueLookup = new SourceLookup();
|
||||||
|
nullValueLookup.setSource(Collections.singletonMap("field", null));
|
||||||
|
|
||||||
|
assertTrue(fetcher.fetchValues(missingValueLookup).isEmpty());
|
||||||
|
assertTrue(fetcher.fetchValues(nullValueLookup).isEmpty());
|
||||||
|
|
||||||
|
MappedFieldType valued = new ConstantKeywordFieldMapper.ConstantKeywordFieldType("field", "foo");
|
||||||
|
fetcher = valued.valueFetcher(null, null, null);
|
||||||
|
|
||||||
|
assertEquals(Collections.singletonList("foo"), fetcher.fetchValues(missingValueLookup));
|
||||||
|
assertEquals(Collections.singletonList("foo"), fetcher.fetchValues(nullValueLookup));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,24 +9,18 @@ package org.elasticsearch.xpack.flattened.mapper;
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.Version;
|
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.bytes.BytesArray;
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.collect.List;
|
|
||||||
import org.elasticsearch.common.compress.CompressedXContent;
|
import org.elasticsearch.common.compress.CompressedXContent;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.index.IndexService;
|
import org.elasticsearch.index.IndexService;
|
||||||
import org.elasticsearch.index.mapper.ContentPath;
|
|
||||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||||
import org.elasticsearch.index.mapper.DocumentMapperParser;
|
import org.elasticsearch.index.mapper.DocumentMapperParser;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
import org.elasticsearch.index.mapper.FieldMapperTestCase;
|
import org.elasticsearch.index.mapper.FieldMapperTestCase;
|
||||||
import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
|
import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
|
||||||
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.MapperService.MergeReason;
|
import org.elasticsearch.index.mapper.MapperService.MergeReason;
|
||||||
|
@ -42,7 +36,6 @@ import org.junit.Before;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.apache.lucene.analysis.BaseTokenStreamTestCase.assertTokenStreamContents;
|
import static org.apache.lucene.analysis.BaseTokenStreamTestCase.assertTokenStreamContents;
|
||||||
|
@ -512,18 +505,4 @@ public class FlatObjectFieldMapperTests extends FieldMapperTestCase<FlatObjectFi
|
||||||
assertTokenStreamContents(keyedFieldType.getTextSearchInfo().getSearchAnalyzer().analyzer().tokenStream("", "Hello World"),
|
assertTokenStreamContents(keyedFieldType.getTextSearchInfo().getSearchAnalyzer().analyzer().tokenStream("", "Hello World"),
|
||||||
new String[] {"Hello", "World"});
|
new String[] {"Hello", "World"});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFetchSourceValue() throws IOException {
|
|
||||||
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
|
||||||
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
|
||||||
|
|
||||||
Map<String, Object> sourceValue = org.elasticsearch.common.collect.Map.of("key", "value");
|
|
||||||
FlatObjectFieldMapper mapper = new FlatObjectFieldMapper.Builder("field").build(context);
|
|
||||||
assertEquals(List.of(sourceValue), fetchSourceValue(mapper, sourceValue));
|
|
||||||
|
|
||||||
FlatObjectFieldMapper nullValueMapper = new FlatObjectFieldMapper.Builder("field")
|
|
||||||
.nullValue("NULL")
|
|
||||||
.build(context);
|
|
||||||
assertEquals(List.of("NULL"), fetchSourceValue(nullValueMapper, null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,7 +178,8 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlatObjectFieldMapper build(BuilderContext context) {
|
public FlatObjectFieldMapper build(BuilderContext context) {
|
||||||
MappedFieldType ft = new RootFlatObjectFieldType(buildFullName(context), indexed, hasDocValues, meta, splitQueriesOnWhitespace);
|
MappedFieldType ft
|
||||||
|
= new RootFlatObjectFieldType(buildFullName(context), indexed, hasDocValues, meta, splitQueriesOnWhitespace, nullValue);
|
||||||
if (eagerGlobalOrdinals) {
|
if (eagerGlobalOrdinals) {
|
||||||
ft.setEagerGlobalOrdinals(true);
|
ft.setEagerGlobalOrdinals(true);
|
||||||
}
|
}
|
||||||
|
@ -324,6 +325,11 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
|
||||||
failIfNoDocValues();
|
failIfNoDocValues();
|
||||||
return new KeyedFlatObjectFieldData.Builder(name(), key, CoreValuesSourceType.BYTES);
|
return new KeyedFlatObjectFieldData.Builder(name(), key, CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
throw new UnsupportedOperationException(); // TODO can we implement this?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,13 +443,15 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
|
||||||
*/
|
*/
|
||||||
public static final class RootFlatObjectFieldType extends StringFieldType {
|
public static final class RootFlatObjectFieldType extends StringFieldType {
|
||||||
private final boolean splitQueriesOnWhitespace;
|
private final boolean splitQueriesOnWhitespace;
|
||||||
|
private final String nullValue;
|
||||||
|
|
||||||
public RootFlatObjectFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta,
|
public RootFlatObjectFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta,
|
||||||
boolean splitQueriesOnWhitespace) {
|
boolean splitQueriesOnWhitespace, String nullValue) {
|
||||||
super(name, indexed, false, hasDocValues,
|
super(name, indexed, false, hasDocValues,
|
||||||
splitQueriesOnWhitespace ? TextSearchInfo.WHITESPACE_MATCH_ONLY : TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
splitQueriesOnWhitespace ? TextSearchInfo.WHITESPACE_MATCH_ONLY : TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
|
||||||
this.splitQueriesOnWhitespace = splitQueriesOnWhitespace;
|
this.splitQueriesOnWhitespace = splitQueriesOnWhitespace;
|
||||||
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
|
||||||
|
this.nullValue = nullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -465,6 +473,19 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
|
||||||
failIfNoDocValues();
|
failIfNoDocValues();
|
||||||
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
return new SortedSetOrdinalsIndexFieldData.Builder(name(), CoreValuesSourceType.BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
||||||
|
if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
||||||
|
}
|
||||||
|
return new SourceValueFetcher(name(), mapperService, false, nullValue) {
|
||||||
|
@Override
|
||||||
|
protected Object parseSourceValue(Object value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FlatObjectFieldParser fieldParser;
|
private FlatObjectFieldParser fieldParser;
|
||||||
|
@ -543,19 +564,6 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) {
|
|
||||||
if (format != null) {
|
|
||||||
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
|
|
||||||
}
|
|
||||||
return new SourceValueFetcher(name(), mapperService, parsesArrayValue(), nullValue) {
|
|
||||||
@Override
|
|
||||||
protected Object parseSourceValue(Object value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||||
super.doXContentBody(builder, includeDefaults, params);
|
super.doXContentBody(builder, includeDefaults, params);
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.xpack.flattened.mapper;
|
||||||
|
|
||||||
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.index.mapper.ContentPath;
|
||||||
|
import org.elasticsearch.index.mapper.FieldTypeTestCase;
|
||||||
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
|
import org.elasticsearch.index.mapper.Mapper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FlatObjectFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
|
public void testFetchSourceValue() throws IOException {
|
||||||
|
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
|
||||||
|
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
|
||||||
|
|
||||||
|
Map<String, Object> sourceValue = org.elasticsearch.common.collect.Map.of("key", "value");
|
||||||
|
MappedFieldType mapper = new FlatObjectFieldMapper.Builder("field").build(context).fieldType();
|
||||||
|
assertEquals(Collections.singletonList(sourceValue), fetchSourceValue(mapper, sourceValue));
|
||||||
|
|
||||||
|
MappedFieldType nullValueMapper = new FlatObjectFieldMapper.Builder("field")
|
||||||
|
.nullValue("NULL")
|
||||||
|
.build(context)
|
||||||
|
.fieldType();
|
||||||
|
assertEquals(Collections.singletonList("NULL"), fetchSourceValue(nullValueMapper, null));
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue