Merge pull request #11644 from rjernst/refactor/field-type-equality

Add equals/hashcode to fieldtypes
This commit is contained in:
Ryan Ernst 2015-06-15 15:42:53 -07:00
commit 7ab0009e41
35 changed files with 1246 additions and 145 deletions

View File

@ -46,6 +46,7 @@ import org.elasticsearch.index.similarity.SimilarityProvider;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* This defines the core properties and functions to operate on a field. * This defines the core properties and functions to operate on a field.
@ -200,6 +201,28 @@ public class MappedFieldType extends FieldType {
return new MappedFieldType(this); return new MappedFieldType(this);
} }
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
MappedFieldType fieldType = (MappedFieldType) o;
return boost == fieldType.boost &&
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 // norelease: we need to override freeze() and add safety checks that all settings are actually set
public boolean isNumeric() { public boolean isNumeric() {

View File

@ -49,6 +49,7 @@ import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.index.mapper.MapperBuilders.binaryField; import static org.elasticsearch.index.mapper.MapperBuilders.binaryField;
import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField;
@ -82,7 +83,7 @@ public class BinaryFieldMapper extends AbstractFieldMapper {
@Override @Override
public BinaryFieldMapper build(BuilderContext context) { public BinaryFieldMapper build(BuilderContext context) {
setupFieldType(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, return new BinaryFieldMapper(fieldType, docValues,
fieldDataSettings, context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo); fieldDataSettings, context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
} }
@ -106,7 +107,7 @@ public class BinaryFieldMapper extends AbstractFieldMapper {
} }
static final class BinaryFieldType extends MappedFieldType { static final class BinaryFieldType extends MappedFieldType {
protected boolean tryUncompressing = false; private boolean tryUncompressing = false;
public BinaryFieldType() { public BinaryFieldType() {
super(AbstractFieldMapper.Defaults.FIELD_TYPE); super(AbstractFieldMapper.Defaults.FIELD_TYPE);
@ -122,6 +123,27 @@ public class BinaryFieldMapper extends AbstractFieldMapper {
return new BinaryFieldType(this); return new BinaryFieldType(this);
} }
@Override
public boolean equals(Object o) {
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 @Override
public BytesReference value(Object value) { public BytesReference value(Object value) {
if (value == null) { if (value == null) {

View File

@ -57,6 +57,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -234,6 +235,19 @@ public class DateFieldMapper extends NumberFieldMapper {
return new DateFieldType(this); return new DateFieldType(this);
} }
@Override
public boolean equals(Object o) {
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.format(), timeUnit);
}
public FormatDateTimeFormatter dateTimeFormatter() { public FormatDateTimeFormatter dateTimeFormatter() {
return dateTimeFormatter; return dateTimeFormatter;
} }

View File

@ -312,6 +312,26 @@ public class GeoPointFieldMapper extends AbstractFieldMapper implements ArrayVal
return new GeoPointFieldType(this); return new GeoPointFieldType(this);
} }
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
GeoPointFieldType that = (GeoPointFieldType) o;
return geohashPrecision == that.geohashPrecision &&
geohashPrefixEnabled == that.geohashPrefixEnabled &&
validateLon == that.validateLon &&
validateLat == that.validateLat &&
normalizeLon == that.normalizeLon &&
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() { public boolean isGeohashEnabled() {
return geohashFieldType != null; return geohashFieldType != null;
} }

View File

@ -51,6 +51,7 @@ import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.index.mapper.MapperBuilders.geoShapeField; 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. * FieldMapper for indexing {@link com.spatial4j.core.shape.Shape}s.
* <p/> * <p/>
* Currently Shapes can only be indexed and can only be queried using * 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. * a lot of behavior in this Mapper is disabled.
* <p/> * <p/>
* Format supported: * Format supported:
@ -91,12 +92,15 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
public static final String STRATEGY = SpatialStrategy.RECURSIVE.getStrategyName(); public static final String STRATEGY = SpatialStrategy.RECURSIVE.getStrategyName();
public static final int GEOHASH_LEVELS = GeoUtils.geoHashLevelsForPrecision("50m"); public static final int GEOHASH_LEVELS = GeoUtils.geoHashLevelsForPrecision("50m");
public static final int QUADTREE_LEVELS = GeoUtils.quadTreeLevelsForPrecision("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 Orientation ORIENTATION = Orientation.RIGHT;
public static final MappedFieldType FIELD_TYPE = new GeoShapeFieldType(); public static final MappedFieldType FIELD_TYPE = new GeoShapeFieldType();
static { 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.setIndexOptions(IndexOptions.DOCS);
FIELD_TYPE.setTokenized(false); FIELD_TYPE.setTokenized(false);
FIELD_TYPE.setStored(false); FIELD_TYPE.setStored(false);
@ -108,91 +112,30 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
public static class Builder extends AbstractFieldMapper.Builder<Builder, GeoShapeFieldMapper> { 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) { public Builder(String name) {
super(name, Defaults.FIELD_TYPE); super(name, Defaults.FIELD_TYPE);
} }
public Builder tree(String tree) { public GeoShapeFieldType fieldType() {
this.tree = tree; return (GeoShapeFieldType)fieldType;
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;
} }
@Override @Override
public GeoShapeFieldMapper build(BuilderContext context) { public GeoShapeFieldMapper build(BuilderContext context) {
GeoShapeFieldType geoShapeFieldType = (GeoShapeFieldType)fieldType;
if (Names.TREE_GEOHASH.equals(tree)) { if (geoShapeFieldType.tree.equals("quadtree") && context.indexCreatedVersion().before(Version.V_2_0_0)) {
prefixTree = new GeohashPrefixTree(ShapeBuilder.SPATIAL_CONTEXT, getLevels(treeLevels, precisionInMeters, Defaults.GEOHASH_LEVELS, true)); geoShapeFieldType.setTree("legacyquadtree");
} 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 (context.indexCreatedVersion().before(Version.V_2_0_0) ||
(geoShapeFieldType.treeLevels() == 0 && geoShapeFieldType.precisionInMeters() < 0)) {
geoShapeFieldType.setDefaultDistanceErrorPct(Defaults.LEGACY_DISTANCE_ERROR_PCT);
} }
setupFieldType(context); 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); 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 { public static class TypeParser implements Mapper.TypeParser {
@ -200,31 +143,27 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
@Override @Override
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException { public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
Builder builder = geoShapeField(name); 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();) { for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, Object> entry = iterator.next(); Map.Entry<String, Object> entry = iterator.next();
String fieldName = Strings.toUnderscoreCase(entry.getKey()); String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue(); Object fieldNode = entry.getValue();
if (Names.TREE.equals(fieldName)) { if (Names.TREE.equals(fieldName)) {
builder.tree(fieldNode.toString()); builder.fieldType().setTree(fieldNode.toString());
iterator.remove(); iterator.remove();
} else if (Names.TREE_LEVELS.equals(fieldName)) { } else if (Names.TREE_LEVELS.equals(fieldName)) {
builder.treeLevels(Integer.parseInt(fieldNode.toString())); builder.fieldType().setTreeLevels(Integer.parseInt(fieldNode.toString()));
iterator.remove(); iterator.remove();
} else if (Names.TREE_PRESISION.equals(fieldName)) { } 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(); iterator.remove();
} else if (Names.DISTANCE_ERROR_PCT.equals(fieldName)) { } else if (Names.DISTANCE_ERROR_PCT.equals(fieldName)) {
builder.distanceErrorPct(Double.parseDouble(fieldNode.toString())); builder.fieldType().setDistanceErrorPct(Double.parseDouble(fieldNode.toString()));
builder.distErrPctDefined = true;
iterator.remove(); iterator.remove();
} else if (Names.ORIENTATION.equals(fieldName)) { } else if (Names.ORIENTATION.equals(fieldName)) {
builder.orientation(ShapeBuilder.orientationFromString(fieldNode.toString())); builder.fieldType().setOrientation(ShapeBuilder.orientationFromString(fieldNode.toString()));
iterator.remove(); iterator.remove();
} else if (Names.STRATEGY.equals(fieldName)) { } else if (Names.STRATEGY.equals(fieldName)) {
builder.strategy(fieldNode.toString()); builder.fieldType().setStrategyName(fieldNode.toString());
iterator.remove(); iterator.remove();
} }
} }
@ -234,10 +173,18 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
public static final class GeoShapeFieldType extends MappedFieldType { 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 PrefixTreeStrategy defaultStrategy;
private RecursivePrefixTreeStrategy recursiveStrategy; private RecursivePrefixTreeStrategy recursiveStrategy;
private TermQueryPrefixTreeStrategy termStrategy; private TermQueryPrefixTreeStrategy termStrategy;
private Orientation orientation;
public GeoShapeFieldType() { public GeoShapeFieldType() {
super(AbstractFieldMapper.Defaults.FIELD_TYPE); super(AbstractFieldMapper.Defaults.FIELD_TYPE);
@ -245,10 +192,12 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
protected GeoShapeFieldType(GeoShapeFieldType ref) { protected GeoShapeFieldType(GeoShapeFieldType ref) {
super(ref); super(ref);
// TODO: this shallow copy is probably not good...need to extract the parameters and recreate the tree and strategies? this.tree = ref.tree;
this.defaultStrategy = ref.defaultStrategy; this.strategyName = ref.strategyName;
this.recursiveStrategy = ref.recursiveStrategy; this.treeLevels = ref.treeLevels;
this.termStrategy = ref.termStrategy; this.precisionInMeters = ref.precisionInMeters;
this.distanceErrorPct = ref.distanceErrorPct;
this.defaultDistanceErrorPct = ref.defaultDistanceErrorPct;
this.orientation = ref.orientation; this.orientation = ref.orientation;
} }
@ -257,6 +206,113 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
return new GeoShapeFieldType(this); return new GeoShapeFieldType(this);
} }
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
GeoShapeFieldType that = (GeoShapeFieldType) o;
return treeLevels == that.treeLevels &&
precisionInMeters == that.precisionInMeters &&
defaultDistanceErrorPct == that.defaultDistanceErrorPct &&
Objects.equals(tree, that.tree) &&
Objects.equals(strategyName, that.strategyName) &&
Objects.equals(distanceErrorPct, that.distanceErrorPct) &&
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();
// This is a bit hackish: we need to setup the spatial tree and strategies once the field name is set, which
// must be by the time freeze is called.
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() { public PrefixTreeStrategy defaultStrategy() {
return this.defaultStrategy; return this.defaultStrategy;
} }
@ -271,26 +327,6 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
throw new IllegalArgumentException("Unknown prefix tree strategy [" + strategyName + "]"); 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 @Override
public String value(Object value) { public String value(Object value) {
throw new UnsupportedOperationException("GeoShape fields cannot be converted to String values"); throw new UnsupportedOperationException("GeoShape fields cannot be converted to String values");
@ -352,25 +388,24 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
return; return;
} }
final GeoShapeFieldMapper fieldMergeWith = (GeoShapeFieldMapper) mergeWith; final GeoShapeFieldMapper fieldMergeWith = (GeoShapeFieldMapper) mergeWith;
final PrefixTreeStrategy mergeWithStrategy = fieldMergeWith.fieldType().defaultStrategy();
// prevent user from changing strategies // 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"); 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) // 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"); 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 // 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 // in lucene's SpatialPrefixTree implementations, need a patch to correct that first
if (grid.getMaxLevels() != mergeGrid.getMaxLevels()) { if (fieldType().treeLevels() != fieldMergeWith.fieldType().treeLevels()) {
mergeResult.addConflict("mapper [" + fieldType.names().fullName() + "] has different tree_levels or precision"); 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 // bail if there were merge conflicts
@ -380,7 +415,7 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper {
// change distance error percent // change distance error percent
this.fieldType = this.fieldType.clone(); 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 // change orientation - this is allowed because existing dateline spanning shapes
// have already been unwound and segmented // have already been unwound and segmented
this.fieldType().setOrientation(fieldMergeWith.fieldType().orientation()); 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 { protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
builder.field("type", contentType()); builder.field("type", contentType());
// TODO: Come up with a better way to get the name, maybe pass it from builder if (includeDefaults || fieldType().tree().equals(Defaults.TREE) == false) {
if (fieldType().defaultStrategy().getGrid() instanceof GeohashPrefixTree) { builder.field(Names.TREE, fieldType().tree());
// 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 { if (includeDefaults || fieldType().treeLevels() != 0) {
builder.field(Names.TREE, Names.TREE_QUADTREE); builder.field(Names.TREE_LEVELS, fieldType().treeLevels());
if (includeDefaults || fieldType().defaultStrategy().getGrid().getMaxLevels() != Defaults.QUADTREE_LEVELS) {
builder.field(Names.TREE_LEVELS, fieldType().defaultStrategy().getGrid().getMaxLevels());
} }
if (includeDefaults || fieldType().precisionInMeters() != -1) {
builder.field(Names.TREE_PRESISION, DistanceUnit.METERS.toString(fieldType().precisionInMeters()));
} }
if (includeDefaults || fieldType().strategyName() != Defaults.STRATEGY) {
if (includeDefaults || fieldType().defaultStrategy().getDistErrPct() != Defaults.DISTANCE_ERROR_PCT) { builder.field(Names.STRATEGY, fieldType().strategyName());
builder.field(Names.DISTANCE_ERROR_PCT, fieldType().defaultStrategy().getDistErrPct()); }
if (includeDefaults || fieldType().distanceErrorPct() != fieldType().defaultDistanceErrorPct) {
builder.field(Names.DISTANCE_ERROR_PCT, fieldType().distanceErrorPct());
} }
if (includeDefaults || fieldType().orientation() != Defaults.ORIENTATION) { if (includeDefaults || fieldType().orientation() != Defaults.ORIENTATION) {
builder.field(Names.ORIENTATION, fieldType().orientation()); builder.field(Names.ORIENTATION, fieldType().orientation());
} }

View File

@ -46,6 +46,7 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue;
import static org.elasticsearch.index.mapper.MapperBuilders.fieldNames; import static org.elasticsearch.index.mapper.MapperBuilders.fieldNames;
@ -148,6 +149,18 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa
this.enabled = ref.enabled; this.enabled = ref.enabled;
} }
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
FieldNamesFieldType that = (FieldNamesFieldType) o;
return enabled == that.enabled;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), enabled);
}
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
checkIfFrozen(); checkIfFrozen();
this.enabled = enabled; this.enabled = enabled;
@ -288,7 +301,7 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa
} }
boolean includeDefaults = params.paramAsBoolean("include_defaults", false); 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; return builder;
} }

View File

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

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, 2 + propNum);
}
}
}

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, 6 + propNum);
}
}
}

View File

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

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, 1 + propNum);
}
}
}

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); DocumentMapper mapper = parser.parse(mapping);
for (String fieldName : Lists.newArrayList("field1", "field2", "field3", "field4")) { for (String fieldName : Lists.newArrayList("field1", "field2", "field3", "field4")) {
Map<String, Object> serializedMap = getSerializedMap(fieldName, mapper); 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. // Cases where search_quote_analyzer should be present.