Mappings: Add equals/hashcode to fieldtypes

In order to restrict a single set of field type settings for a given
field name across an index, we need the ability to compare field types.
This change adds equals and hashcode, as well as tests for every field
type.
This commit is contained in:
Ryan Ernst 2015-06-10 09:38:44 -07:00
parent 3a97f322f7
commit 0ef5a27556
35 changed files with 1256 additions and 145 deletions

View File

@ -46,6 +46,7 @@ import org.elasticsearch.index.similarity.SimilarityProvider;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
/**
* This defines the core properties and functions to operate on a field.
@ -200,7 +201,31 @@ public class MappedFieldType extends FieldType {
return new MappedFieldType(this);
}
// norelease: we need to override freeze() and add safety checks that all settings are actually set
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MappedFieldType)) return false;
if (!super.equals(o)) return false;
MappedFieldType fieldType = (MappedFieldType) o;
return Objects.equals(boost, fieldType.boost) &&
Objects.equals(docValues, fieldType.docValues) &&
Objects.equals(names, fieldType.names) &&
Objects.equals(indexAnalyzer, fieldType.indexAnalyzer) &&
Objects.equals(searchAnalyzer, fieldType.searchAnalyzer) &&
Objects.equals(searchQuoteAnalyzer(), fieldType.searchQuoteAnalyzer()) &&
Objects.equals(similarity, fieldType.similarity) &&
Objects.equals(normsLoading, fieldType.normsLoading) &&
Objects.equals(fieldDataType, fieldType.fieldDataType) &&
Objects.equals(nullValue, fieldType.nullValue) &&
Objects.equals(nullValueAsString, fieldType.nullValueAsString);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), names, boost, docValues, indexAnalyzer, searchAnalyzer, searchQuoteAnalyzer, similarity, normsLoading, fieldDataType, nullValue, nullValueAsString);
}
// norelease: we need to override freeze() and add safety checks that all settings are actually set
public boolean isNumeric() {
return false;

View File

@ -49,6 +49,7 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.index.mapper.MapperBuilders.binaryField;
import static org.elasticsearch.index.mapper.core.TypeParsers.parseField;
@ -82,7 +83,7 @@ public class BinaryFieldMapper extends AbstractFieldMapper {
@Override
public BinaryFieldMapper build(BuilderContext context) {
setupFieldType(context);
((BinaryFieldType)fieldType).tryUncompressing = context.indexCreatedVersion().before(Version.V_2_0_0);
((BinaryFieldType)fieldType).setTryUncompressing(context.indexCreatedVersion().before(Version.V_2_0_0));
return new BinaryFieldMapper(fieldType, docValues,
fieldDataSettings, context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
}
@ -106,7 +107,7 @@ public class BinaryFieldMapper extends AbstractFieldMapper {
}
static final class BinaryFieldType extends MappedFieldType {
protected boolean tryUncompressing = false;
private boolean tryUncompressing = false;
public BinaryFieldType() {
super(AbstractFieldMapper.Defaults.FIELD_TYPE);
@ -122,6 +123,29 @@ public class BinaryFieldMapper extends AbstractFieldMapper {
return new BinaryFieldType(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BinaryFieldType)) return false;
if (!super.equals(o)) return false;
BinaryFieldType that = (BinaryFieldType) o;
return Objects.equals(tryUncompressing, that.tryUncompressing);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), tryUncompressing);
}
public boolean tryUncompressing() {
return tryUncompressing;
}
public void setTryUncompressing(boolean tryUncompressing) {
checkIfFrozen();
this.tryUncompressing = tryUncompressing;
}
@Override
public BytesReference value(Object value) {
if (value == null) {

View File

@ -57,6 +57,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
@ -234,6 +235,21 @@ public class DateFieldMapper extends NumberFieldMapper {
return new DateFieldType(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DateFieldType)) return false;
if (!super.equals(o)) return false;
DateFieldType that = (DateFieldType) o;
return Objects.equals(dateTimeFormatter.format(), that.dateTimeFormatter.format()) &&
Objects.equals(timeUnit, that.timeUnit);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), dateTimeFormatter, timeUnit);
}
public FormatDateTimeFormatter dateTimeFormatter() {
return dateTimeFormatter;
}

View File

@ -312,6 +312,28 @@ public class GeoPointFieldMapper extends AbstractFieldMapper implements ArrayVal
return new GeoPointFieldType(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GeoPointFieldType)) return false;
if (!super.equals(o)) return false;
GeoPointFieldType that = (GeoPointFieldType) o;
return java.util.Objects.equals(geohashPrecision, that.geohashPrecision) &&
java.util.Objects.equals(geohashPrefixEnabled, that.geohashPrefixEnabled) &&
java.util.Objects.equals(validateLon, that.validateLon) &&
java.util.Objects.equals(validateLat, that.validateLat) &&
java.util.Objects.equals(normalizeLon, that.normalizeLon) &&
java.util.Objects.equals(normalizeLat, that.normalizeLat) &&
java.util.Objects.equals(geohashFieldType, that.geohashFieldType) &&
java.util.Objects.equals(latFieldType, that.latFieldType) &&
java.util.Objects.equals(lonFieldType, that.lonFieldType);
}
@Override
public int hashCode() {
return java.util.Objects.hash(super.hashCode(), geohashFieldType, geohashPrecision, geohashPrefixEnabled, latFieldType, lonFieldType, validateLon, validateLat, normalizeLon, normalizeLat);
}
public boolean isGeohashEnabled() {
return geohashFieldType != null;
}

View File

@ -51,6 +51,7 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.index.mapper.MapperBuilders.geoShapeField;
@ -59,7 +60,7 @@ import static org.elasticsearch.index.mapper.MapperBuilders.geoShapeField;
* FieldMapper for indexing {@link com.spatial4j.core.shape.Shape}s.
* <p/>
* Currently Shapes can only be indexed and can only be queried using
* {@link org.elasticsearch.index.query.GeoShapeFilterParser}, consequently
* {@link org.elasticsearch.index.query.GeoShapeQueryParser}, consequently
* a lot of behavior in this Mapper is disabled.
* <p/>
* Format supported:
@ -91,12 +92,15 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
public static final String STRATEGY = SpatialStrategy.RECURSIVE.getStrategyName();
public static final int GEOHASH_LEVELS = GeoUtils.geoHashLevelsForPrecision("50m");
public static final int QUADTREE_LEVELS = GeoUtils.quadTreeLevelsForPrecision("50m");
public static final double DISTANCE_ERROR_PCT = 0.025d;
public static final double LEGACY_DISTANCE_ERROR_PCT = 0.025d;
public static final Orientation ORIENTATION = Orientation.RIGHT;
public static final MappedFieldType FIELD_TYPE = new GeoShapeFieldType();
static {
// setting name here is a hack so freeze can be called...instead all these options should be
// moved to the default ctor for GeoShapeFieldType, and defaultFieldType() should be removed from mappers...
FIELD_TYPE.setNames(new MappedFieldType.Names("DoesNotExist"));
FIELD_TYPE.setIndexOptions(IndexOptions.DOCS);
FIELD_TYPE.setTokenized(false);
FIELD_TYPE.setStored(false);
@ -108,91 +112,30 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
public static class Builder extends AbstractFieldMapper.Builder<Builder, GeoShapeFieldMapper> {
private String tree = Defaults.TREE;
private String strategyName = Defaults.STRATEGY;
private int treeLevels = 0;
private double precisionInMeters = -1;
private double distanceErrorPct = Defaults.DISTANCE_ERROR_PCT;
private boolean distErrPctDefined;
private Orientation orientation = Defaults.ORIENTATION;
private SpatialPrefixTree prefixTree;
public Builder(String name) {
super(name, Defaults.FIELD_TYPE);
}
public Builder tree(String tree) {
this.tree = tree;
return this;
}
public Builder strategy(String strategy) {
this.strategyName = strategy;
return this;
}
public Builder treeLevelsByDistance(double meters) {
this.precisionInMeters = meters;
return this;
}
public Builder treeLevels(int treeLevels) {
this.treeLevels = treeLevels;
return this;
}
public Builder distanceErrorPct(double distanceErrorPct) {
this.distanceErrorPct = distanceErrorPct;
return this;
}
public Builder orientation(Orientation orientation) {
this.orientation = orientation;
return this;
public GeoShapeFieldType fieldType() {
return (GeoShapeFieldType)fieldType;
}
@Override
public GeoShapeFieldMapper build(BuilderContext context) {
GeoShapeFieldType geoShapeFieldType = (GeoShapeFieldType)fieldType;
if (Names.TREE_GEOHASH.equals(tree)) {
prefixTree = new GeohashPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults.GEOHASH_LEVELS, true));
} else if (Names.TREE_QUADTREE.equals(tree)) {
if (context.indexCreatedVersion().before(Version.V_1_6_0)) {
prefixTree = new QuadPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults
.QUADTREE_LEVELS, false));
} else {
prefixTree = new PackedQuadPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults
.QUADTREE_LEVELS, false));
}
} else {
throw new IllegalArgumentException("Unknown prefix tree type [" + tree + "]");
if (geoShapeFieldType.tree.equals("quadtree") && context.indexCreatedVersion().before(Version.V_2_0_0)) {
geoShapeFieldType.setTree("legacyquadtree");
}
if (context.indexCreatedVersion().before(Version.V_2_0_0) ||
(geoShapeFieldType.treeLevels() == 0 && geoShapeFieldType.precisionInMeters() < 0)) {
geoShapeFieldType.setDefaultDistanceErrorPct(Defaults.LEGACY_DISTANCE_ERROR_PCT);
}
setupFieldType(context);
RecursivePrefixTreeStrategy recursiveStrategy = new RecursivePrefixTreeStrategy(prefixTree, fieldType.names().indexName());
recursiveStrategy.setDistErrPct(distanceErrorPct);
recursiveStrategy.setPruneLeafyBranches(false);
TermQueryPrefixTreeStrategy termStrategy = new TermQueryPrefixTreeStrategy(prefixTree, fieldType.names().indexName());
termStrategy.setDistErrPct(distanceErrorPct);
GeoShapeFieldType geoShapeFieldType = (GeoShapeFieldType)fieldType;
geoShapeFieldType.setStrategies(strategyName, recursiveStrategy, termStrategy);
geoShapeFieldType.setOrientation(orientation);
return new GeoShapeFieldMapper(fieldType, context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
}
private final int getLevels(int treeLevels, double precisionInMeters, int defaultLevels, boolean geoHash) {
if (treeLevels > 0 || precisionInMeters >= 0) {
// if the user specified a precision but not a distance error percent then zero out the distance err pct
// this is done to guarantee precision specified by the user without doing something unexpected under the covers
if (!distErrPctDefined) distanceErrorPct = 0;
return Math.max(treeLevels, precisionInMeters >= 0 ? (geoHash ? GeoUtils.geoHashLevelsForPrecision(precisionInMeters)
: GeoUtils.quadTreeLevelsForPrecision(precisionInMeters)) : 0);
}
return defaultLevels;
}
}
public static class TypeParser implements Mapper.TypeParser {
@ -200,31 +143,27 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
@Override
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
Builder builder = geoShapeField(name);
// if index was created before 1.6, this conditional should be true (this forces any index created on/or after 1.6 to use 0 for
// the default distanceErrorPct parameter).
builder.distErrPctDefined = parserContext.indexVersionCreated().before(Version.V_1_6_0);
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, Object> entry = iterator.next();
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
if (Names.TREE.equals(fieldName)) {
builder.tree(fieldNode.toString());
builder.fieldType().setTree(fieldNode.toString());
iterator.remove();
} else if (Names.TREE_LEVELS.equals(fieldName)) {
builder.treeLevels(Integer.parseInt(fieldNode.toString()));
builder.fieldType().setTreeLevels(Integer.parseInt(fieldNode.toString()));
iterator.remove();
} else if (Names.TREE_PRESISION.equals(fieldName)) {
builder.treeLevelsByDistance(DistanceUnit.parse(fieldNode.toString(), DistanceUnit.DEFAULT, DistanceUnit.DEFAULT));
builder.fieldType().setPrecisionInMeters(DistanceUnit.parse(fieldNode.toString(), DistanceUnit.DEFAULT, DistanceUnit.DEFAULT));
iterator.remove();
} else if (Names.DISTANCE_ERROR_PCT.equals(fieldName)) {
builder.distanceErrorPct(Double.parseDouble(fieldNode.toString()));
builder.distErrPctDefined = true;
builder.fieldType().setDistanceErrorPct(Double.parseDouble(fieldNode.toString()));
iterator.remove();
} else if (Names.ORIENTATION.equals(fieldName)) {
builder.orientation(ShapeBuilder.orientationFromString(fieldNode.toString()));
builder.fieldType().setOrientation(ShapeBuilder.orientationFromString(fieldNode.toString()));
iterator.remove();
} else if (Names.STRATEGY.equals(fieldName)) {
builder.strategy(fieldNode.toString());
builder.fieldType().setStrategyName(fieldNode.toString());
iterator.remove();
}
}
@ -234,10 +173,18 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
public static final class GeoShapeFieldType extends MappedFieldType {
private String tree = Defaults.TREE;
private String strategyName = Defaults.STRATEGY;
private int treeLevels = 0;
private double precisionInMeters = -1;
private Double distanceErrorPct;
private double defaultDistanceErrorPct = 0.0;
private Orientation orientation = Defaults.ORIENTATION;
// these are built when the field type is frozen
private PrefixTreeStrategy defaultStrategy;
private RecursivePrefixTreeStrategy recursiveStrategy;
private TermQueryPrefixTreeStrategy termStrategy;
private Orientation orientation;
public GeoShapeFieldType() {
super(AbstractFieldMapper.Defaults.FIELD_TYPE);
@ -245,10 +192,12 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
protected GeoShapeFieldType(GeoShapeFieldType ref) {
super(ref);
// TODO: this shallow copy is probably not good...need to extract the parameters and recreate the tree and strategies?
this.defaultStrategy = ref.defaultStrategy;
this.recursiveStrategy = ref.recursiveStrategy;
this.termStrategy = ref.termStrategy;
this.tree = ref.tree;
this.strategyName = ref.strategyName;
this.treeLevels = ref.treeLevels;
this.precisionInMeters = ref.precisionInMeters;
this.distanceErrorPct = ref.distanceErrorPct;
this.defaultDistanceErrorPct = ref.defaultDistanceErrorPct;
this.orientation = ref.orientation;
}
@ -257,6 +206,113 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
return new GeoShapeFieldType(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GeoShapeFieldType)) return false;
if (!super.equals(o)) return false;
GeoShapeFieldType that = (GeoShapeFieldType) o;
return Objects.equals(treeLevels, that.treeLevels) &&
Objects.equals(precisionInMeters, that.precisionInMeters) &&
Objects.equals(defaultDistanceErrorPct, that.defaultDistanceErrorPct) &&
Objects.equals(tree, that.tree) &&
Objects.equals(strategyName, that.strategyName) &&
Objects.equals(distanceErrorPct, that.distanceErrorPct) &&
Objects.equals(orientation, that.orientation);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), tree, strategyName, treeLevels, precisionInMeters, distanceErrorPct, defaultDistanceErrorPct, orientation);
}
@Override
public void freeze() {
super.freeze();
SpatialPrefixTree prefixTree;
if ("geohash".equals(tree)) {
prefixTree = new GeohashPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults.GEOHASH_LEVELS, true));
} else if ("legacyquadtree".equals(tree)) {
prefixTree = new QuadPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults.QUADTREE_LEVELS, false));
} else if ("quadtree".equals(tree)) {
prefixTree = new PackedQuadPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults.QUADTREE_LEVELS, false));
} else {
throw new IllegalArgumentException("Unknown prefix tree type [" + tree + "]");
}
recursiveStrategy = new RecursivePrefixTreeStrategy(prefixTree, names().indexName());
recursiveStrategy.setDistErrPct(distanceErrorPct());
recursiveStrategy.setPruneLeafyBranches(false);
termStrategy = new TermQueryPrefixTreeStrategy(prefixTree, names().indexName());
termStrategy.setDistErrPct(distanceErrorPct());
defaultStrategy = resolveStrategy(strategyName);
}
private static int getLevels(int treeLevels, double precisionInMeters, int defaultLevels, boolean geoHash) {
if (treeLevels > 0 || precisionInMeters >= 0) {
return Math.max(treeLevels, precisionInMeters >= 0 ? (geoHash ? GeoUtils.geoHashLevelsForPrecision(precisionInMeters)
: GeoUtils.quadTreeLevelsForPrecision(precisionInMeters)) : 0);
}
return defaultLevels;
}
public String tree() {
return tree;
}
public void setTree(String tree) {
checkIfFrozen();
this.tree = tree;
}
public String strategyName() {
return strategyName;
}
public void setStrategyName(String strategyName) {
checkIfFrozen();
this.strategyName = strategyName;
}
public int treeLevels() {
return treeLevels;
}
public void setTreeLevels(int treeLevels) {
checkIfFrozen();
this.treeLevels = treeLevels;
}
public double precisionInMeters() {
return precisionInMeters;
}
public void setPrecisionInMeters(double precisionInMeters) {
checkIfFrozen();
this.precisionInMeters = precisionInMeters;
}
public double distanceErrorPct() {
return distanceErrorPct == null ? defaultDistanceErrorPct : distanceErrorPct;
}
public void setDistanceErrorPct(double distanceErrorPct) {
checkIfFrozen();
this.distanceErrorPct = distanceErrorPct;
}
public void setDefaultDistanceErrorPct(double defaultDistanceErrorPct) {
checkIfFrozen();
this.defaultDistanceErrorPct = defaultDistanceErrorPct;
}
public Orientation orientation() { return this.orientation; }
public void setOrientation(Orientation orientation) {
checkIfFrozen();
this.orientation = orientation;
}
public PrefixTreeStrategy defaultStrategy() {
return this.defaultStrategy;
}
@ -271,26 +327,6 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
throw new IllegalArgumentException("Unknown prefix tree strategy [" + strategyName + "]");
}
public void setStrategies(String defaultStrategy, RecursivePrefixTreeStrategy recursiveStrategy, TermQueryPrefixTreeStrategy termStrategy) {
checkIfFrozen();
this.recursiveStrategy = recursiveStrategy;
this.termStrategy = termStrategy;
this.defaultStrategy = resolveStrategy(defaultStrategy);
}
public void setDistErrPct(double distErrPct) {
checkIfFrozen();
this.recursiveStrategy.setDistErrPct(distErrPct);
this.termStrategy.setDistErrPct(distErrPct);
}
public Orientation orientation() { return this.orientation; }
public void setOrientation(Orientation orientation) {
checkIfFrozen();
this.orientation = orientation;
}
@Override
public String value(Object value) {
throw new UnsupportedOperationException("GeoShape fields cannot be converted to String values");
@ -352,25 +388,24 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
return;
}
final GeoShapeFieldMapper fieldMergeWith = (GeoShapeFieldMapper) mergeWith;
final PrefixTreeStrategy mergeWithStrategy = fieldMergeWith.fieldType().defaultStrategy();
// prevent user from changing strategies
if (!(this.fieldType().defaultStrategy().getClass().equals(mergeWithStrategy.getClass()))) {
if (fieldType().strategyName().equals(fieldMergeWith.fieldType().strategyName()) == false) {
mergeResult.addConflict("mapper [" + fieldType.names().fullName() + "] has different strategy");
}
final SpatialPrefixTree grid = this.fieldType().defaultStrategy().getGrid();
final SpatialPrefixTree mergeGrid = mergeWithStrategy.getGrid();
// prevent user from changing trees (changes encoding)
if (!grid.getClass().equals(mergeGrid.getClass())) {
if (fieldType().tree().equals(fieldMergeWith.fieldType().tree()) == false) {
mergeResult.addConflict("mapper [" + fieldType.names().fullName() + "] has different tree");
}
// TODO we should allow this, but at the moment levels is used to build bookkeeping variables
// in lucene's SpatialPrefixTree implementations, need a patch to correct that first
if (grid.getMaxLevels() != mergeGrid.getMaxLevels()) {
mergeResult.addConflict("mapper [" + fieldType.names().fullName() + "] has different tree_levels or precision");
if (fieldType().treeLevels() != fieldMergeWith.fieldType().treeLevels()) {
mergeResult.addConflict("mapper [" + fieldType.names().fullName() + "] has different tree_levels");
}
if (fieldType().precisionInMeters() != fieldMergeWith.fieldType().precisionInMeters()) {
mergeResult.addConflict("mapper [" + fieldType.names().fullName() + "] has different precision");
}
// bail if there were merge conflicts
@ -380,7 +415,7 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
// change distance error percent
this.fieldType = this.fieldType.clone();
this.fieldType().setDistErrPct(mergeWithStrategy.getDistErrPct());
this.fieldType().setDistanceErrorPct(fieldMergeWith.fieldType().distanceErrorPct());
// change orientation - this is allowed because existing dateline spanning shapes
// have already been unwound and segmented
this.fieldType().setOrientation(fieldMergeWith.fieldType().orientation());
@ -395,24 +430,21 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
builder.field("type", contentType());
// TODO: Come up with a better way to get the name, maybe pass it from builder
if (fieldType().defaultStrategy().getGrid() instanceof GeohashPrefixTree) {
// Don't emit the tree name since GeohashPrefixTree is the default
// Only emit the tree levels if it isn't the default value
if (includeDefaults || fieldType().defaultStrategy().getGrid().getMaxLevels() != Defaults.GEOHASH_LEVELS) {
builder.field(Names.TREE_LEVELS, fieldType().defaultStrategy().getGrid().getMaxLevels());
}
} else {
builder.field(Names.TREE, Names.TREE_QUADTREE);
if (includeDefaults || fieldType().defaultStrategy().getGrid().getMaxLevels() != Defaults.QUADTREE_LEVELS) {
builder.field(Names.TREE_LEVELS, fieldType().defaultStrategy().getGrid().getMaxLevels());
}
if (includeDefaults || fieldType().tree().equals(Defaults.TREE) == false) {
builder.field(Names.TREE, fieldType().tree());
}
if (includeDefaults || fieldType().defaultStrategy().getDistErrPct() != Defaults.DISTANCE_ERROR_PCT) {
builder.field(Names.DISTANCE_ERROR_PCT, fieldType().defaultStrategy().getDistErrPct());
if (includeDefaults || fieldType().treeLevels() != 0) {
builder.field(Names.TREE_LEVELS, fieldType().treeLevels());
}
if (includeDefaults || fieldType().precisionInMeters() != -1) {
builder.field(Names.TREE_PRESISION, DistanceUnit.METERS.toString(fieldType().precisionInMeters()));
}
if (includeDefaults || fieldType().strategyName() != Defaults.STRATEGY) {
builder.field(Names.STRATEGY, fieldType().strategyName());
}
if (includeDefaults || fieldType().distanceErrorPct() != fieldType().defaultDistanceErrorPct) {
builder.field(Names.DISTANCE_ERROR_PCT, fieldType().distanceErrorPct());
}
if (includeDefaults || fieldType().orientation() != Defaults.ORIENTATION) {
builder.field(Names.ORIENTATION, fieldType().orientation());
}

View File

@ -46,6 +46,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue;
import static org.elasticsearch.index.mapper.MapperBuilders.fieldNames;
@ -148,6 +149,20 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa
this.enabled = ref.enabled;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FieldNamesFieldType)) return false;
if (!super.equals(o)) return false;
FieldNamesFieldType that = (FieldNamesFieldType) o;
return Objects.equals(enabled, that.enabled);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), enabled);
}
public void setEnabled(boolean enabled) {
checkIfFrozen();
this.enabled = enabled;
@ -288,7 +303,7 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa
}
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
if (includeDefaults == false && fieldType().equals(Defaults.FIELD_TYPE) && fieldType().isEnabled() == Defaults.ENABLED) {
if (includeDefaults == false && fieldType().isEnabled() == Defaults.ENABLED) {
return builder;
}

View File

@ -229,12 +229,10 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper
}
private final String type;
private final BytesRef typeAsBytes;
protected ParentFieldMapper(MappedFieldType fieldType, String type, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(fieldType, Version.indexCreated(indexSettings).onOrAfter(Version.V_2_0_0), fieldDataSettings, indexSettings);
this.type = type;
this.typeAsBytes = type == null ? null : new BytesRef(type);
}
public ParentFieldMapper(Settings indexSettings) {

View File

@ -0,0 +1,126 @@
/*
* 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.common.lucene.Lucene;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.similarity.BM25SimilarityProvider;
import org.elasticsearch.test.ElasticsearchTestCase;
/** Base test case for subclasses of MappedFieldType */
public abstract class FieldTypeTestCase extends ElasticsearchTestCase {
/** Create a default constructed fieldtype */
protected abstract MappedFieldType createDefaultFieldType();
/** A dummy null value to use when modifying null value */
protected Object dummyNullValue() {
return "dummyvalue";
}
/** Returns the number of properties that can be modified for the fieldtype */
protected int numProperties() {
return 10;
}
/** Modifies a property, identified by propNum, on the given fieldtype */
protected void modifyProperty(MappedFieldType ft, int propNum) {
switch (propNum) {
case 0: ft.setNames(new MappedFieldType.Names("dummy")); break;
case 1: ft.setBoost(1.1f); break;
case 2: ft.setHasDocValues(!ft.hasDocValues()); break;
case 3: ft.setIndexAnalyzer(Lucene.STANDARD_ANALYZER); break;
case 4: ft.setSearchAnalyzer(Lucene.STANDARD_ANALYZER); break;
case 5: ft.setSearchQuoteAnalyzer(Lucene.STANDARD_ANALYZER); break;
case 6: ft.setSimilarity(new BM25SimilarityProvider("foo", Settings.EMPTY)); break;
case 7: ft.setNormsLoading(MappedFieldType.Loading.LAZY); break;
case 8: ft.setFieldDataType(new FieldDataType("foo", Settings.builder().put("loading", "eager").build())); break;
case 9: ft.setNullValue(dummyNullValue()); break;
default: fail("unknown fieldtype property number " + propNum);
}
}
// TODO: remove this once toString is no longer final on FieldType...
protected void assertEquals(int i, MappedFieldType ft1, MappedFieldType ft2) {
assertEquals("prop " + i + "\nexpected: " + toString(ft1) + "; \nactual: " + toString(ft2), ft1, ft2);
}
protected String toString(MappedFieldType ft) {
return "MappedFieldType{" +
"names=" + ft.names() +
", boost=" + ft.boost() +
", docValues=" + ft.hasDocValues() +
", indexAnalyzer=" + ft.indexAnalyzer() +
", searchAnalyzer=" + ft.searchAnalyzer() +
", searchQuoteAnalyzer=" + ft.searchQuoteAnalyzer() +
", similarity=" + ft.similarity() +
", normsLoading=" + ft.normsLoading() +
", fieldDataType=" + ft.fieldDataType() +
", nullValue=" + ft.nullValue() +
", nullValueAsString='" + ft.nullValueAsString() + "'" +
"} " + super.toString();
}
public void testClone() {
MappedFieldType fieldType = createDefaultFieldType();
MappedFieldType clone = fieldType.clone();
assertNotSame(clone, fieldType);
assertEquals(clone.getClass(), fieldType.getClass());
assertEquals(clone, fieldType);
assertEquals(clone, clone.clone()); // transitivity
for (int i = 0; i < numProperties(); ++i) {
fieldType = createDefaultFieldType();
modifyProperty(fieldType, i);
clone = fieldType.clone();
assertNotSame(clone, fieldType);
assertEquals(i, clone, fieldType);
}
}
public void testEquals() {
MappedFieldType ft1 = createDefaultFieldType();
MappedFieldType ft2 = createDefaultFieldType();
assertEquals(ft1, ft1); // reflexive
assertEquals(ft1, ft2); // symmetric
assertEquals(ft2, ft1);
assertEquals(ft1.hashCode(), ft2.hashCode());
for (int i = 0; i < numProperties(); ++i) {
ft2 = createDefaultFieldType();
modifyProperty(ft2, i);
assertNotEquals(ft1, ft2);
assertNotEquals(ft1.hashCode(), ft2.hashCode());
}
}
public void testFreeze() {
for (int i = 0; i < numProperties(); ++i) {
MappedFieldType fieldType = createDefaultFieldType();
fieldType.freeze();
try {
modifyProperty(fieldType, i);
fail("expected already frozen exception for property " + i);
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("already frozen"));
}
}
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.mapper;
public class MappedFieldTypeTests extends FieldTypeTestCase {
@Override
public MappedFieldType createDefaultFieldType() {
return new MappedFieldType();
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class BinaryFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new BinaryFieldMapper.BinaryFieldType();
}
@Override
protected int numProperties() {
return 1 + super.numProperties();
}
@Override
protected void modifyProperty(MappedFieldType ft, int propNum) {
BinaryFieldMapper.BinaryFieldType bft = (BinaryFieldMapper.BinaryFieldType)ft;
switch (propNum) {
case 0: bft.setTryUncompressing(!bft.tryUncompressing()); break;
default: super.modifyProperty(ft, numProperties() - propNum - 1);
}
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class BooleanFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new BooleanFieldMapper.BooleanFieldType();
}
@Override
protected Object dummyNullValue() {
return true;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class ByteFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new ByteFieldMapper.ByteFieldType();
}
@Override
protected Object dummyNullValue() {
return (byte)10;
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class CompletionFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new CompletionFieldMapper.CompletionFieldType();
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.core;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
public class DateFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new DateFieldMapper.DateFieldType();
}
@Override
protected Object dummyNullValue() {
return 10;
}
@Override
protected int numProperties() {
return 2 + super.numProperties();
}
@Override
protected void modifyProperty(MappedFieldType ft, int propNum) {
DateFieldMapper.DateFieldType dft = (DateFieldMapper.DateFieldType)ft;
switch (propNum) {
case 0: dft.setDateTimeFormatter(Joda.forPattern("basic_week_date", Locale.ROOT)); break;
case 1: dft.setTimeUnit(TimeUnit.HOURS); break;
default: super.modifyProperty(ft, numProperties() - propNum - 1);
}
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class DoubleFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new DoubleFieldMapper.DoubleFieldType();
}
@Override
protected Object dummyNullValue() {
return 10.0D;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class FloatFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new DoubleFieldMapper.DoubleFieldType();
}
@Override
protected Object dummyNullValue() {
return 10.0;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class IntegerFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new IntegerFieldMapper.IntegerFieldType();
}
@Override
protected Object dummyNullValue() {
return 10;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class LongFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new LongFieldMapper.LongFieldType();
}
@Override
protected Object dummyNullValue() {
return (long)10;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class ShortFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new ShortFieldMapper.ShortFieldType();
}
@Override
protected Object dummyNullValue() {
return (short)10;
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.core;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class StringFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new StringFieldMapper.StringFieldType();
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.geo;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class GeoPointFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new GeoPointFieldMapper.GeoPointFieldType();
}
@Override
protected int numProperties() {
return 6 + super.numProperties();
}
@Override
protected void modifyProperty(MappedFieldType ft, int propNum) {
GeoPointFieldMapper.GeoPointFieldType gft = (GeoPointFieldMapper.GeoPointFieldType)ft;
switch (propNum) {
case 0: gft.setGeohashEnabled(new MappedFieldType(), 1, true); break;
case 1: gft.setLatLonEnabled(new MappedFieldType(), new MappedFieldType()); break;
case 2: gft.setValidateLon(!gft.validateLon()); break;
case 3: gft.setValidateLat(!gft.validateLat()); break;
case 4: gft.setNormalizeLon(!gft.normalizeLon()); break;
case 5: gft.setNormalizeLat(!gft.normalizeLat()); break;
default: super.modifyProperty(ft, numProperties() - propNum - 1);
}
}
}

View File

@ -57,7 +57,7 @@ public class GeoShapeFieldMapperTests extends ElasticsearchSingleNodeTest {
GeoShapeFieldMapper geoShapeFieldMapper = (GeoShapeFieldMapper) fieldMapper;
PrefixTreeStrategy strategy = geoShapeFieldMapper.fieldType().defaultStrategy();
assertThat(strategy.getDistErrPct(), equalTo(GeoShapeFieldMapper.Defaults.DISTANCE_ERROR_PCT));
assertThat(strategy.getDistErrPct(), equalTo(GeoShapeFieldMapper.Defaults.LEGACY_DISTANCE_ERROR_PCT));
assertThat(strategy.getGrid(), instanceOf(GeohashPrefixTree.class));
assertThat(strategy.getGrid().getMaxLevels(), equalTo(GeoShapeFieldMapper.Defaults.GEOHASH_LEVELS));
assertThat(geoShapeFieldMapper.fieldType().orientation(), equalTo(GeoShapeFieldMapper.Defaults.ORIENTATION));
@ -340,11 +340,12 @@ public class GeoShapeFieldMapperTests extends ElasticsearchSingleNodeTest {
MergeResult mergeResult = stage1.merge(stage2.mapping(), false);
// check correct conflicts
assertThat(mergeResult.hasConflicts(), equalTo(true));
assertThat(mergeResult.buildConflicts().length, equalTo(3));
assertThat(mergeResult.buildConflicts().length, equalTo(4));
ArrayList conflicts = new ArrayList<>(Arrays.asList(mergeResult.buildConflicts()));
assertThat("mapper [shape] has different strategy", isIn(conflicts));
assertThat("mapper [shape] has different tree", isIn(conflicts));
assertThat("mapper [shape] has different tree_levels or precision", isIn(conflicts));
assertThat("mapper [shape] has different tree_levels", isIn(conflicts));
assertThat("mapper [shape] has different precision", isIn(conflicts));
// verify nothing changed
FieldMapper fieldMapper = stage1.mappers().getMapper("shape");
@ -362,12 +363,12 @@ public class GeoShapeFieldMapperTests extends ElasticsearchSingleNodeTest {
// correct mapping
stage2Mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("shape").field("type", "geo_shape").field("precision", "1m")
.field("distance_error_pct", 0.001).field("orientation", "cw").endObject().endObject().endObject().endObject().string();
.field("tree_levels", 8).field("distance_error_pct", 0.001).field("orientation", "cw").endObject().endObject().endObject().endObject().string();
stage2 = parser.parse(stage2Mapping);
mergeResult = stage1.merge(stage2.mapping(), false);
// verify mapping changes, and ensure no failures
assertThat(mergeResult.hasConflicts(), equalTo(false));
assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false));
fieldMapper = stage1.mappers().getMapper("shape");
assertThat(fieldMapper, instanceOf(GeoShapeFieldMapper.class));

View File

@ -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.geo;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class GeoShapeFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
GeoShapeFieldMapper.GeoShapeFieldType gft = new GeoShapeFieldMapper.GeoShapeFieldType();
gft.setNames(new MappedFieldType.Names("testgeoshape"));
return gft;
}
@Override
protected int numProperties() {
return 6 + super.numProperties();
}
@Override
protected void modifyProperty(MappedFieldType ft, int propNum) {
GeoShapeFieldMapper.GeoShapeFieldType gft = (GeoShapeFieldMapper.GeoShapeFieldType)ft;
switch (propNum) {
case 0: gft.setTree("quadtree"); break;
case 1: gft.setStrategyName("term"); break;
case 2: gft.setTreeLevels(10); break;
case 3: gft.setPrecisionInMeters(20); break;
case 4: gft.setDefaultDistanceErrorPct(0.5); break;
case 5: gft.setOrientation(ShapeBuilder.Orientation.LEFT); break;
default: super.modifyProperty(ft, numProperties() - propNum - 1);
}
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class AllFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new AllFieldMapper.AllFieldType();
}
}

View File

@ -0,0 +1,43 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class FieldNamesFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new FieldNamesFieldMapper.FieldNamesFieldType();
}
@Override
protected int numProperties() {
return 1 + super.numProperties();
}
@Override
protected void modifyProperty(MappedFieldType ft, int propNum) {
FieldNamesFieldMapper.FieldNamesFieldType fnft = (FieldNamesFieldMapper.FieldNamesFieldType)ft;
switch (propNum) {
case 0: fnft.setEnabled(!fnft.isEnabled()); break;
default: super.modifyProperty(ft, numProperties() - propNum - 1);
}
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class IdFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new IdFieldMapper.IdFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class IndexFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new IndexFieldMapper.IndexFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class ParentFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new ParentFieldMapper.ParentFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class RoutingFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new RoutingFieldMapper.RoutingFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class SourceFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new SourceFieldMapper.SourceFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.core.DateFieldTypeTests;
public class TimestampFieldTypeTests extends DateFieldTypeTests {
@Override
protected MappedFieldType createDefaultFieldType() {
return new TimestampFieldMapper.TimestampFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class TypeFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new TypeFieldMapper.TypeFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class UidFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new UidFieldMapper.UidFieldType();
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.internal;
import org.elasticsearch.index.mapper.FieldTypeTestCase;
import org.elasticsearch.index.mapper.MappedFieldType;
public class VersionFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new VersionFieldMapper.VersionFieldType();
}
}

View File

@ -252,7 +252,7 @@ public class SimpleStringMappingTests extends ElasticsearchSingleNodeTest {
DocumentMapper mapper = parser.parse(mapping);
for (String fieldName : Lists.newArrayList("field1", "field2", "field3", "field4")) {
Map<String, Object> serializedMap = getSerializedMap(fieldName, mapper);
assertFalse(serializedMap.containsKey("search_quote_analyzer"));
assertFalse(fieldName, serializedMap.containsKey("search_quote_analyzer"));
}
// Cases where search_quote_analyzer should be present.