diff options
author | Nicholas Knize <nknize@gmail.com> | 2016-08-24 13:53:38 -0500 |
---|---|---|
committer | Nicholas Knize <nknize@gmail.com> | 2016-09-13 12:17:36 -0500 |
commit | ef926894f428f782073170173f2b1d144f42062f (patch) | |
tree | 7b53240d91558a4e31957afe3a377611cce64bee | |
parent | e0074ee9d44440affae0ebf30c3172409f1e21f0 (diff) |
Cut over geo_point field and queries to new LatLonPoint type
This commit cuts over geo_point fields to use Lucene's new point-based LatLonPoint type for indexes created in 5.0. Indexes created prior to 5.0 continue to use their respective encoding type. Below is a description of the changes made to support the new encoding type:
* New indexes use a new LatLonPointFieldMapper which provides a parse method for the new type
* The new LatLonPoint parse method removes support for lat_lon and geohash parameters
* Backcompat testing for deprecated lat_lon and geohash parameters is added to all unit and integration tests
* LatLonPointFieldMapper provides DocValues support (enabled by default) which uses Lucene's new LatLonDocValuesField type
* New LatLonPoint field data classes are added for aggregation support (wraps LatLonPoint's Numeric Doc Values)
* MultiFields use the geohash as the string value instead of the lat,lon string making it easier to perform geo string queries on the geohash instead of a lat,lon comma delimited string.
Removed Features:
* With the removal of geohash indexing, GeoHashCellQuery support is removed for all new indexes (still supported on existing indexes)
* LatLonPoint does not support a Distance Range query because it is super inefficient. Instead, the geo_distance_range query should be accomplished using either the geo_distance aggregation, sorting by descending distance on a geo_distance query, or a boolean must not of the excluded distance (which is what the distance_range query did anyway).
TODO:
* fix/finish yaml changes for plugin and rest integration tests
* update documentation
34 files changed, 956 insertions, 504 deletions
diff --git a/core/src/main/java/org/elasticsearch/common/geo/GeoPoint.java b/core/src/main/java/org/elasticsearch/common/geo/GeoPoint.java index 504fc41313..aaa552fbec 100644 --- a/core/src/main/java/org/elasticsearch/common/geo/GeoPoint.java +++ b/core/src/main/java/org/elasticsearch/common/geo/GeoPoint.java @@ -19,8 +19,13 @@ package org.elasticsearch.common.geo; +import org.apache.lucene.document.LatLonDocValuesField; +import org.apache.lucene.document.LatLonPoint; +import org.apache.lucene.geo.GeoEncodingUtils; +import org.apache.lucene.index.IndexableField; import org.apache.lucene.spatial.geopoint.document.GeoPointField; import org.apache.lucene.util.BitUtil; +import org.apache.lucene.util.NumericUtils; import static org.elasticsearch.common.geo.GeoHashUtils.mortonEncode; import static org.elasticsearch.common.geo.GeoHashUtils.stringEncode; @@ -88,6 +93,23 @@ public final class GeoPoint { return this; } + // todo this is a crutch because LatLonPoint doesn't have a helper for returning .stringValue() + // todo remove with next release of lucene + public GeoPoint resetFromIndexableField(IndexableField field) { + if (field instanceof LatLonPoint) { + byte[] bytes = field.binaryValue().bytes; + return this.reset( + GeoEncodingUtils.decodeLatitude(bytes, 0), + GeoEncodingUtils.decodeLongitude(bytes, Integer.BYTES)); + } else if (field instanceof LatLonDocValuesField) { + long encoded = (long)(field.numericValue()); + return this.reset( + GeoEncodingUtils.decodeLatitude((int)(encoded >>> 32)), + GeoEncodingUtils.decodeLongitude((int)encoded)); + } + return resetFromIndexHash(Long.parseLong(field.stringValue())); + } + public GeoPoint resetFromGeoHash(String geohash) { final long hash = mortonEncode(geohash); return this.reset(GeoPointField.decodeLatitude(hash), GeoPointField.decodeLongitude(hash)); diff --git a/core/src/main/java/org/elasticsearch/index/fielddata/plain/AbstractLatLonPointDVIndexFieldData.java b/core/src/main/java/org/elasticsearch/index/fielddata/plain/AbstractLatLonPointDVIndexFieldData.java new file mode 100644 index 0000000000..c4198a2689 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/fielddata/plain/AbstractLatLonPointDVIndexFieldData.java @@ -0,0 +1,100 @@ +/* + * 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.fielddata.plain; + +import org.apache.lucene.document.LatLonDocValuesField; +import org.apache.lucene.index.DocValues; +import org.apache.lucene.index.DocValuesType; +import org.apache.lucene.index.FieldInfo; +import org.apache.lucene.index.LeafReader; +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.index.Index; +import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.fielddata.AtomicGeoPointFieldData; +import org.elasticsearch.index.fielddata.IndexFieldData; +import org.elasticsearch.index.fielddata.IndexFieldDataCache; +import org.elasticsearch.index.fielddata.IndexGeoPointFieldData; +import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.indices.breaker.CircuitBreakerService; +import org.elasticsearch.search.MultiValueMode; + +import java.io.IOException; + +/** + * Created by nknize on 8/23/16. + */ +public abstract class AbstractLatLonPointDVIndexFieldData extends DocValuesIndexFieldData + implements IndexGeoPointFieldData { + AbstractLatLonPointDVIndexFieldData(Index index, String fieldName) { + super(index, fieldName); + } + + @Override + public final XFieldComparatorSource comparatorSource(@Nullable Object missingValue, MultiValueMode sortMode, + XFieldComparatorSource.Nested nested) { + throw new IllegalArgumentException("can't sort on geo_point field without using specific sorting feature, like geo_distance"); + } + + public static class LatLonPointDVIndexFieldData extends AbstractLatLonPointDVIndexFieldData { + public LatLonPointDVIndexFieldData(Index index, String fieldName) { + super(index, fieldName); + } + + @Override + public AtomicGeoPointFieldData load(LeafReaderContext context) { + try { + LeafReader reader = context.reader(); + FieldInfo info = reader.getFieldInfos().fieldInfo(fieldName); + if (info != null) { + checkCompatible(info); + } + return new LatLonPointDVAtomicFieldData(DocValues.getSortedNumeric(reader, fieldName)); + } catch (IOException e) { + throw new IllegalStateException("Cannot load doc values", e); + } + } + + @Override + public AtomicGeoPointFieldData loadDirect(LeafReaderContext context) throws Exception { + return load(context); + } + + /** helper: checks a fieldinfo and throws exception if its definitely not a LatLonDocValuesField */ + static void checkCompatible(FieldInfo fieldInfo) { + // dv properties could be "unset", if you e.g. used only StoredField with this same name in the segment. + if (fieldInfo.getDocValuesType() != DocValuesType.NONE + && fieldInfo.getDocValuesType() != LatLonDocValuesField.TYPE.docValuesType()) { + throw new IllegalArgumentException("field=\"" + fieldInfo.name + "\" was indexed with docValuesType=" + + fieldInfo.getDocValuesType() + " but this type has docValuesType=" + + LatLonDocValuesField.TYPE.docValuesType() + ", is the field really a LatLonDocValuesField?"); + } + } + } + + public static class Builder implements IndexFieldData.Builder { + @Override + public IndexFieldData<?> build(IndexSettings indexSettings, MappedFieldType fieldType, IndexFieldDataCache cache, + CircuitBreakerService breakerService, MapperService mapperService) { + // ignore breaker + return new LatLonPointDVIndexFieldData(indexSettings.getIndex(), fieldType.name()); + } + } +} diff --git a/core/src/main/java/org/elasticsearch/index/fielddata/plain/LatLonPointDVAtomicFieldData.java b/core/src/main/java/org/elasticsearch/index/fielddata/plain/LatLonPointDVAtomicFieldData.java new file mode 100644 index 0000000000..420233b5e6 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/fielddata/plain/LatLonPointDVAtomicFieldData.java @@ -0,0 +1,94 @@ +/* + * 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.fielddata.plain; + +import org.apache.lucene.geo.GeoEncodingUtils; +import org.apache.lucene.index.SortedNumericDocValues; +import org.apache.lucene.util.Accountable; +import org.apache.lucene.util.ArrayUtil; +import org.apache.lucene.util.RamUsageEstimator; +import org.elasticsearch.common.geo.GeoPoint; +import org.elasticsearch.index.fielddata.MultiGeoPointValues; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * Created by nknize on 8/23/16. + */ +final class LatLonPointDVAtomicFieldData extends AbstractAtomicGeoPointFieldData { + private final SortedNumericDocValues values; + + LatLonPointDVAtomicFieldData(SortedNumericDocValues values) { + super(); + this.values = values; + } + + @Override + public long ramBytesUsed() { + return 0; // not exposed by lucene + } + + @Override + public Collection<Accountable> getChildResources() { + return Collections.emptyList(); + } + + @Override + public void close() { + // noop + } + + @Override + public MultiGeoPointValues getGeoPointValues() { + return new MultiGeoPointValues() { + GeoPoint[] points = new GeoPoint[0]; + private int count = 0; + + @Override + public void setDocument(int docId) { + values.setDocument(docId); + count = values.count(); + if (count > points.length) { + final int previousLength = points.length; + points = Arrays.copyOf(points, ArrayUtil.oversize(count, RamUsageEstimator.NUM_BYTES_OBJECT_REF)); + for (int i = previousLength; i < points.length; ++i) { + points[i] = new GeoPoint(Double.NaN, Double.NaN); + } + } + long encoded; + for (int i=0; i<count; ++i) { + encoded = values.valueAt(i); + points[i].reset(GeoEncodingUtils.decodeLatitude((int)(encoded >>> 32)), GeoEncodingUtils.decodeLongitude((int)encoded)); + } + } + + @Override + public int count() { + return count; + } + + @Override + public GeoPoint valueAt(int index) { + return points[index]; + } + }; + } +} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/BaseGeoPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/BaseGeoPointFieldMapper.java index 2a24b6a94c..b64c09553c 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/BaseGeoPointFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/BaseGeoPointFieldMapper.java @@ -89,7 +89,7 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr protected Boolean ignoreMalformed; - public Builder(String name, GeoPointFieldType fieldType) { + public Builder(String name, MappedFieldType fieldType) { super(name, fieldType, fieldType); } @@ -143,7 +143,16 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr FieldMapper geoHashMapper, MultiFields multiFields, Explicit<Boolean> ignoreMalformed, CopyTo copyTo); public Y build(Mapper.BuilderContext context) { - GeoPointFieldType geoPointFieldType = (GeoPointFieldType)fieldType; + // version 5.0 cuts over to LatLonPoint and no longer indexes geohash, or lat/lon separately + if (context.indexCreatedVersion().before(Version.V_5_0_0_alpha6)) { + return buildLegacy(context); + } + return build(context, name, fieldType, defaultFieldType, context.indexSettings(), + null, null, null, multiFieldsBuilder.build(this, context), ignoreMalformed(context), copyTo); + } + + private Y buildLegacy(Mapper.BuilderContext context) { + LegacyGeoPointFieldType geoPointFieldType = (LegacyGeoPointFieldType)fieldType; FieldMapper latMapper = null; FieldMapper lonMapper = null; @@ -161,9 +170,9 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr lonMapper = (LegacyDoubleFieldMapper) lonMapperBuilder.includeInAll(false).store(fieldType.stored()).docValues(false).build(context); } else { latMapper = new NumberFieldMapper.Builder(Names.LAT, NumberFieldMapper.NumberType.DOUBLE) - .includeInAll(false).store(fieldType.stored()).docValues(false).build(context); + .includeInAll(false).store(fieldType.stored()).docValues(false).build(context); lonMapper = new NumberFieldMapper.Builder(Names.LON, NumberFieldMapper.NumberType.DOUBLE) - .includeInAll(false).store(fieldType.stored()).docValues(false).build(context); + .includeInAll(false).store(fieldType.stored()).docValues(false).build(context); } geoPointFieldType.setLatLonEnabled(latMapper.fieldType(), lonMapper.fieldType()); } @@ -183,7 +192,7 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr context.path().remove(); return build(context, name, fieldType, defaultFieldType, context.indexSettings(), - latMapper, lonMapper, geoHashMapper, multiFieldsBuilder.build(this, context), ignoreMalformed(context), copyTo); + latMapper, lonMapper, geoHashMapper, multiFieldsBuilder.build(this, context), ignoreMalformed(context), copyTo); } } @@ -191,8 +200,11 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr @Override public Mapper.Builder<?, ?> parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException { Builder builder; - if (parserContext.indexVersionCreated().before(Version.V_2_2_0)) { + Version indexVersionCreated = parserContext.indexVersionCreated(); + if (indexVersionCreated.before(Version.V_2_2_0)) { builder = new LegacyGeoPointFieldMapper.Builder(name); + } else if (indexVersionCreated.onOrAfter(Version.V_5_0_0_alpha6)) { + builder = new LatLonPointFieldMapper.Builder(name); } else { builder = new GeoPointFieldMapper.Builder(name); } @@ -202,39 +214,43 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr Map.Entry<String, Object> entry = iterator.next(); String propName = entry.getKey(); Object propNode = entry.getValue(); - if (propName.equals("lat_lon")) { - deprecationLogger.deprecated(CONTENT_TYPE + " lat_lon parameter is deprecated and will be removed " - + "in the next major release"); - builder.enableLatLon(XContentMapValues.lenientNodeBooleanValue(propNode)); - iterator.remove(); - } else if (propName.equals("precision_step")) { - deprecationLogger.deprecated(CONTENT_TYPE + " precision_step parameter is deprecated and will be removed " - + "in the next major release"); - builder.precisionStep(XContentMapValues.nodeIntegerValue(propNode)); - iterator.remove(); - } else if (propName.equals("geohash")) { - deprecationLogger.deprecated(CONTENT_TYPE + " geohash parameter is deprecated and will be removed " - + "in the next major release"); - builder.enableGeoHash(XContentMapValues.lenientNodeBooleanValue(propNode)); - iterator.remove(); - } else if (propName.equals("geohash_prefix")) { - deprecationLogger.deprecated(CONTENT_TYPE + " geohash_prefix parameter is deprecated and will be removed " - + "in the next major release"); - builder.geoHashPrefix(XContentMapValues.lenientNodeBooleanValue(propNode)); - if (XContentMapValues.lenientNodeBooleanValue(propNode)) { - builder.enableGeoHash(true); - } - iterator.remove(); - } else if (propName.equals("geohash_precision")) { - deprecationLogger.deprecated(CONTENT_TYPE + " geohash_precision parameter is deprecated and will be removed " - + "in the next major release"); - if (propNode instanceof Integer) { - builder.geoHashPrecision(XContentMapValues.nodeIntegerValue(propNode)); - } else { - builder.geoHashPrecision(GeoUtils.geoHashLevelsForPrecision(propNode.toString())); + if (indexVersionCreated.before(Version.V_5_0_0_alpha6)) { + if (propName.equals("lat_lon")) { + deprecationLogger.deprecated(CONTENT_TYPE + " lat_lon parameter is deprecated and will be removed " + + "in the next major release"); + builder.enableLatLon(XContentMapValues.lenientNodeBooleanValue(propNode)); + iterator.remove(); + } else if (propName.equals("precision_step")) { + deprecationLogger.deprecated(CONTENT_TYPE + " precision_step parameter is deprecated and will be removed " + + "in the next major release"); + builder.precisionStep(XContentMapValues.nodeIntegerValue(propNode)); + iterator.remove(); + } else if (propName.equals("geohash")) { + deprecationLogger.deprecated(CONTENT_TYPE + " geohash parameter is deprecated and will be removed " + + "in the next major release"); + builder.enableGeoHash(XContentMapValues.lenientNodeBooleanValue(propNode)); + iterator.remove(); + } else if (propName.equals("geohash_prefix")) { + deprecationLogger.deprecated(CONTENT_TYPE + " geohash_prefix parameter is deprecated and will be removed " + + "in the next major release"); + builder.geoHashPrefix(XContentMapValues.lenientNodeBooleanValue(propNode)); + if (XContentMapValues.lenientNodeBooleanValue(propNode)) { + builder.enableGeoHash(true); + } + iterator.remove(); + } else if (propName.equals("geohash_precision")) { + deprecationLogger.deprecated(CONTENT_TYPE + " geohash_precision parameter is deprecated and will be removed " + + "in the next major release"); + if (propNode instanceof Integer) { + builder.geoHashPrecision(XContentMapValues.nodeIntegerValue(propNode)); + } else { + builder.geoHashPrecision(GeoUtils.geoHashLevelsForPrecision(propNode.toString())); + } + iterator.remove(); } - iterator.remove(); - } else if (propName.equals(Names.IGNORE_MALFORMED)) { + } + + if (propName.equals(Names.IGNORE_MALFORMED)) { builder.ignoreMalformed(XContentMapValues.lenientNodeBooleanValue(propNode)); iterator.remove(); } @@ -242,13 +258,29 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr if (builder instanceof LegacyGeoPointFieldMapper.Builder) { return LegacyGeoPointFieldMapper.parse((LegacyGeoPointFieldMapper.Builder) builder, node, parserContext); + } else if (builder instanceof LatLonPointFieldMapper.Builder) { + return (LatLonPointFieldMapper.Builder) builder; } return (GeoPointFieldMapper.Builder) builder; } } - public static class GeoPointFieldType extends MappedFieldType { + public abstract static class GeoPointFieldType extends MappedFieldType { + GeoPointFieldType() { + } + + GeoPointFieldType(GeoPointFieldType ref) { + super(ref); + } + + @Override + public String typeName() { + return CONTENT_TYPE; + } + } + + public static class LegacyGeoPointFieldType extends GeoPointFieldType { protected MappedFieldType geoHashFieldType; protected int geoHashPrecision; protected boolean geoHashPrefixEnabled; @@ -256,9 +288,9 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr protected MappedFieldType latFieldType; protected MappedFieldType lonFieldType; - GeoPointFieldType() {} + LegacyGeoPointFieldType() {} - GeoPointFieldType(GeoPointFieldType ref) { + LegacyGeoPointFieldType(LegacyGeoPointFieldType ref) { super(ref); this.geoHashFieldType = ref.geoHashFieldType; // copying ref is ok, this can never be modified this.geoHashPrecision = ref.geoHashPrecision; @@ -269,13 +301,13 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr @Override public MappedFieldType clone() { - return new GeoPointFieldType(this); + return new LegacyGeoPointFieldType(this); } @Override public boolean equals(Object o) { if (!super.equals(o)) return false; - GeoPointFieldType that = (GeoPointFieldType) o; + LegacyGeoPointFieldType that = (LegacyGeoPointFieldType) o; return geoHashPrecision == that.geoHashPrecision && geoHashPrefixEnabled == that.geoHashPrefixEnabled && java.util.Objects.equals(geoHashFieldType, that.geoHashFieldType) && @@ -290,14 +322,9 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr } @Override - public String typeName() { - return CONTENT_TYPE; - } - - @Override public void checkCompatibility(MappedFieldType fieldType, List<String> conflicts, boolean strict) { super.checkCompatibility(fieldType, conflicts, strict); - GeoPointFieldType other = (GeoPointFieldType)fieldType; + LegacyGeoPointFieldType other = (LegacyGeoPointFieldType)fieldType; if (isLatLonEnabled() != other.isLatLonEnabled()) { conflicts.add("mapper [" + name() + "] has different [lat_lon]"); } @@ -398,9 +425,10 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr this.ignoreMalformed = ignoreMalformed; } - @Override - public GeoPointFieldType fieldType() { - return (GeoPointFieldType) super.fieldType(); + + + public LegacyGeoPointFieldType legacyFieldType() { + return (LegacyGeoPointFieldType) super.fieldType(); } @Override @@ -414,15 +442,22 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr @Override public Iterator<Mapper> iterator() { + if (this instanceof LatLonPointFieldMapper == false) { + return Iterators.concat(super.iterator(), legacyIterator()); + } + return super.iterator(); + } + + public Iterator<Mapper> legacyIterator() { List<Mapper> extras = new ArrayList<>(); - if (fieldType().isGeoHashEnabled()) { + if (legacyFieldType().isGeoHashEnabled()) { extras.add(geoHashMapper); } - if (fieldType().isLatLonEnabled()) { + if (legacyFieldType().isLatLonEnabled()) { extras.add(latMapper); extras.add(lonMapper); } - return Iterators.concat(super.iterator(), extras.iterator()); + return extras.iterator(); } @Override @@ -436,13 +471,13 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr } protected void parse(ParseContext context, GeoPoint point, String geoHash) throws IOException { - if (fieldType().isGeoHashEnabled()) { + if (legacyFieldType().isGeoHashEnabled()) { if (geoHash == null) { geoHash = GeoHashUtils.stringEncode(point.lon(), point.lat()); } addGeoHashField(context, geoHash); } - if (fieldType().isLatLonEnabled()) { + if (legacyFieldType().isLatLonEnabled()) { latMapper.parse(context.createExternalValueContext(point.lat())); lonMapper.parse(context.createExternalValueContext(point.lon())); } @@ -517,8 +552,9 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr } private void addGeoHashField(ParseContext context, String geoHash) throws IOException { - int len = Math.min(fieldType().geoHashPrecision(), geoHash.length()); - int min = fieldType().isGeoHashPrefixEnabled() ? 1 : len; + LegacyGeoPointFieldType ft = (LegacyGeoPointFieldType)fieldType; + int len = Math.min(ft.geoHashPrecision(), geoHash.length()); + int min = ft.isGeoHashPrefixEnabled() ? 1 : len; for (int i = len; i >= min; i--) { // side effect of this call is adding the field @@ -537,23 +573,30 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr @Override protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException { super.doXContentBody(builder, includeDefaults, params); - if (includeDefaults || fieldType().isLatLonEnabled() != GeoPointFieldMapper.Defaults.ENABLE_LATLON) { - builder.field("lat_lon", fieldType().isLatLonEnabled()); + if (this instanceof LatLonPointFieldMapper == false) { + legacyDoXContentBody(builder, includeDefaults, params); } - if (fieldType().isLatLonEnabled() && (includeDefaults || fieldType().latFieldType().numericPrecisionStep() != LegacyNumericUtils.PRECISION_STEP_DEFAULT)) { - builder.field("precision_step", fieldType().latFieldType().numericPrecisionStep()); + if (includeDefaults || ignoreMalformed.explicit()) { + builder.field(Names.IGNORE_MALFORMED, ignoreMalformed.value()); } - if (includeDefaults || fieldType().isGeoHashEnabled() != Defaults.ENABLE_GEOHASH) { - builder.field("geohash", fieldType().isGeoHashEnabled()); + } + + protected void legacyDoXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException { + LegacyGeoPointFieldType ft = (LegacyGeoPointFieldType) fieldType; + if (includeDefaults || ft.isLatLonEnabled() != GeoPointFieldMapper.Defaults.ENABLE_LATLON) { + builder.field("lat_lon", ft.isLatLonEnabled()); } - if (includeDefaults || fieldType().isGeoHashPrefixEnabled() != Defaults.ENABLE_GEOHASH_PREFIX) { - builder.field("geohash_prefix", fieldType().isGeoHashPrefixEnabled()); + if (ft.isLatLonEnabled() && (includeDefaults || ft.latFieldType().numericPrecisionStep() != LegacyNumericUtils.PRECISION_STEP_DEFAULT)) { + builder.field("precision_step", ft.latFieldType().numericPrecisionStep()); } - if (fieldType().isGeoHashEnabled() && (includeDefaults || fieldType().geoHashPrecision() != Defaults.GEO_HASH_PRECISION)) { - builder.field("geohash_precision", fieldType().geoHashPrecision()); + if (includeDefaults || ft.isGeoHashEnabled() != Defaults.ENABLE_GEOHASH) { + builder.field("geohash", ft.isGeoHashEnabled()); } - if (includeDefaults || ignoreMalformed.explicit()) { - builder.field(Names.IGNORE_MALFORMED, ignoreMalformed.value()); + if (includeDefaults || ft.isGeoHashPrefixEnabled() != Defaults.ENABLE_GEOHASH_PREFIX) { + builder.field("geohash_prefix", ft.isGeoHashPrefixEnabled()); + } + if (ft.isGeoHashEnabled() && (includeDefaults || ft.geoHashPrecision() != Defaults.GEO_HASH_PRECISION)) { + builder.field("geohash_precision", ft.geoHashPrecision()); } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index ee7a9fa07f..c1ba15be78 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -48,7 +48,7 @@ public class GeoPointFieldMapper extends BaseGeoPointFieldMapper { public static class Defaults extends BaseGeoPointFieldMapper.Defaults { - public static final GeoPointFieldType FIELD_TYPE = new GeoPointFieldType(); + public static final GeoPointFieldType FIELD_TYPE = new LegacyGeoPointFieldType(); static { FIELD_TYPE.setIndexOptions(IndexOptions.DOCS); @@ -130,4 +130,9 @@ public class GeoPointFieldMapper extends BaseGeoPointFieldMapper { } super.parse(context, point, geoHash); } + + @Override + public LegacyGeoPointFieldType fieldType() { + return (LegacyGeoPointFieldType) super.fieldType(); + } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/LatLonPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/LatLonPointFieldMapper.java new file mode 100644 index 0000000000..588ef9c373 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/mapper/LatLonPointFieldMapper.java @@ -0,0 +1,148 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.elasticsearch.index.mapper; + +import org.apache.lucene.document.LatLonDocValuesField; +import org.apache.lucene.document.LatLonPoint; +import org.apache.lucene.index.IndexOptions; +import org.apache.lucene.search.Query; +import org.elasticsearch.common.Explicit; +import org.elasticsearch.common.geo.GeoPoint; +import org.elasticsearch.common.geo.GeoUtils; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.fielddata.IndexFieldData; +import org.elasticsearch.index.fielddata.plain.AbstractLatLonPointDVIndexFieldData; +import org.elasticsearch.index.query.QueryShardContext; +import org.elasticsearch.index.query.QueryShardException; + +import java.io.IOException; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by nknize on 8/23/16. + */ +public class LatLonPointFieldMapper extends BaseGeoPointFieldMapper { + public static final String CONTENT_TYPE = "geo_point"; + + public static class Defaults extends BaseGeoPointFieldMapper.Defaults { + public static final LatLonPointFieldType FIELD_TYPE = new LatLonPointFieldType(); + + static { + FIELD_TYPE.setTokenized(false); + FIELD_TYPE.setHasDocValues(true); + FIELD_TYPE.setDimensions(2, Integer.BYTES); + FIELD_TYPE.freeze(); + } + } + + public static class Builder extends BaseGeoPointFieldMapper.Builder<Builder, LatLonPointFieldMapper> { + public Builder(String name) { + super(name, Defaults.FIELD_TYPE); + } + + @Override + public LatLonPointFieldMapper build(BuilderContext context, String simpleName, MappedFieldType fieldType, + MappedFieldType defaultFieldType, Settings indexSettings, + FieldMapper latMapper, FieldMapper lonMapper, FieldMapper geoHashMapper, + MultiFields multiFields, Explicit<Boolean> ignoreMalformed, + CopyTo copyTo) { + setupFieldType(context); + return new LatLonPointFieldMapper(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, + ignoreMalformed, copyTo); + } + + @Override + public LatLonPointFieldMapper build(BuilderContext context) { + return super.build(context); + } + } + + public static class TypeParser extends BaseGeoPointFieldMapper.TypeParser { + @Override + public Mapper.Builder<?, ?> parse(String name, Map<String, Object> node, ParserContext parserContext) + throws MapperParsingException { + return super.parse(name, node, parserContext); + } + } + + public LatLonPointFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType, + Settings indexSettings, MultiFields multiFields, Explicit<Boolean> ignoreMalformed, + CopyTo copyTo) { + super(simpleName, fieldType, defaultFieldType, indexSettings, null, null, null, multiFields, ignoreMalformed, copyTo); + } + + public static class LatLonPointFieldType extends GeoPointFieldType { + LatLonPointFieldType() { + } + + LatLonPointFieldType(LatLonPointFieldType ref) { + super(ref); + } + + @Override + public String typeName() { + return CONTENT_TYPE; + } + + @Override + public MappedFieldType clone() { + return new LatLonPointFieldType(this); + } + + @Override + public IndexFieldData.Builder fielddataBuilder() { + failIfNoDocValues(); + return new AbstractLatLonPointDVIndexFieldData.Builder(); + } + + @Override + public Query termQuery(Object value, QueryShardContext context) { + throw new QueryShardException(context, "Geo fields do not support exact searching, use dedicated geo queries instead: [" + + name() + "]"); + } + } + + @Override + protected void parse(ParseContext originalContext, GeoPoint point, String geoHash) throws IOException { + // Geopoint fields, by default, will not be included in _all + final ParseContext context = originalContext.setIncludeInAllDefault(false); + + if (ignoreMalformed.value() == false) { + if (point.lat() > 90.0 || point.lat() < -90.0) { + throw new IllegalArgumentException("illegal latitude value [" + point.lat() + "] for " + name()); + } + if (point.lon() > 180.0 || point.lon() < -180) { + throw new IllegalArgumentException("illegal longitude value [" + point.lon() + "] for " + name()); + } + } else { + GeoUtils.normalizePoint(point); + } + if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { + context.doc().add(new LatLonPoint(fieldType().name(), point.lat(), point.lon())); + } + if (fieldType.hasDocValues()) { + context.doc().add(new LatLonDocValuesField(fieldType().name(), point.lat(), point.lon())); + } + // if the mapping contains multifields then use the geohash string + if (multiFields.iterator().hasNext()) { + multiFields.parse(this, context.createExternalValueContext(point.geohash())); + } + } +} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/LegacyGeoPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/LegacyGeoPointFieldMapper.java index 3fe195c5d9..99ca07b06b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/LegacyGeoPointFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/LegacyGeoPointFieldMapper.java @@ -60,7 +60,7 @@ public class LegacyGeoPointFieldMapper extends BaseGeoPointFieldMapper implement public static class Defaults extends BaseGeoPointFieldMapper.Defaults{ public static final Explicit<Boolean> COERCE = new Explicit<>(false, false); - public static final GeoPointFieldType FIELD_TYPE = new GeoPointFieldType(); + public static final GeoPointFieldType FIELD_TYPE = new LegacyGeoPointFieldType(); static { FIELD_TYPE.setIndexOptions(IndexOptions.DOCS); @@ -331,6 +331,11 @@ public class LegacyGeoPointFieldMapper extends BaseGeoPointFieldMapper implement } } + @Override + public LegacyGeoPointFieldType fieldType() { + return (LegacyGeoPointFieldType) super.fieldType(); + } + public static class CustomGeoPointDocValuesField extends CustomDocValuesField { private final ObjectHashSet<GeoPoint> points; diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java index ee7220111f..45e84254bf 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java @@ -19,6 +19,7 @@ package org.elasticsearch.index.query; +import org.apache.lucene.document.LatLonPoint; import org.apache.lucene.geo.Rectangle; import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; @@ -38,7 +39,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.fielddata.IndexGeoPointFieldData; import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; -import org.elasticsearch.index.mapper.LegacyGeoPointFieldMapper; +import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper.LegacyGeoPointFieldType; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.search.geo.LegacyInMemoryGeoBoundingBoxQuery; import org.elasticsearch.index.search.geo.LegacyIndexedGeoBoundingBoxQuery; @@ -359,7 +360,10 @@ public class GeoBoundingBoxQueryBuilder extends AbstractQueryBuilder<GeoBounding } } - if (indexVersionCreated.onOrAfter(Version.V_2_2_0)) { + if (indexVersionCreated.onOrAfter(Version.V_5_0_0_alpha6)) { + return LatLonPoint.newBoxQuery(fieldType.name(), luceneBottomRight.getLat(), luceneTopLeft.getLat(), + luceneTopLeft.getLon(), luceneBottomRight.getLon()); + } else if (indexVersionCreated.onOrAfter(Version.V_2_2_0)) { // if index created V_2_2 use (soon to be legacy) numeric encoding postings format // if index created V_2_3 > use prefix encoded postings format final GeoPointField.TermEncoding encoding = (indexVersionCreated.before(Version.V_2_3_0)) ? @@ -371,7 +375,7 @@ public class GeoBoundingBoxQueryBuilder extends AbstractQueryBuilder<GeoBounding Query query; switch(type) { case INDEXED: - LegacyGeoPointFieldMapper.GeoPointFieldType geoFieldType = ((LegacyGeoPointFieldMapper.GeoPointFieldType) fieldType); + LegacyGeoPointFieldType geoFieldType = ((LegacyGeoPointFieldType) fieldType); query = LegacyIndexedGeoBoundingBoxQuery.create(luceneTopLeft, luceneBottomRight, geoFieldType); break; case MEMORY: diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java index a0226f44f7..436f854bc2 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java @@ -19,6 +19,7 @@ package org.elasticsearch.index.query; +import org.apache.lucene.document.LatLonPoint; import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.spatial.geopoint.document.GeoPointField; @@ -297,8 +298,10 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue double normDistance = geoDistance.normalize(this.distance, DistanceUnit.DEFAULT); - if (indexVersionCreated.before(Version.V_2_2_0)) { - LegacyGeoPointFieldMapper.GeoPointFieldType geoFieldType = ((LegacyGeoPointFieldMapper.GeoPointFieldType) fieldType); + if (indexVersionCreated.onOrAfter(Version.V_5_0_0_alpha6)) { + return LatLonPoint.newDistanceQuery(fieldType.name(), center.lat(), center.lon(), normDistance); + } else if (indexVersionCreated.before(Version.V_2_2_0)) { + LegacyGeoPointFieldMapper.LegacyGeoPointFieldType geoFieldType = (LegacyGeoPointFieldMapper.LegacyGeoPointFieldType) fieldType; IndexGeoPointFieldData indexFieldData = shardContext.getForField(fieldType); String bboxOptimization = Strings.isEmpty(optimizeBbox) ? DEFAULT_OPTIMIZE_BBOX : optimizeBbox; return new GeoDistanceRangeQuery(center, null, normDistance, true, false, geoDistance, diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java index 0b06e07e02..ebd80b9e28 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java @@ -37,8 +37,8 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.fielddata.IndexGeoPointFieldData; import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; +import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper.LegacyGeoPointFieldType; import org.elasticsearch.index.mapper.GeoPointFieldMapper; -import org.elasticsearch.index.mapper.LegacyGeoPointFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery; @@ -347,8 +347,11 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan } final Version indexVersionCreated = context.indexVersionCreated(); - if (indexVersionCreated.before(Version.V_2_2_0)) { - LegacyGeoPointFieldMapper.GeoPointFieldType geoFieldType = ((LegacyGeoPointFieldMapper.GeoPointFieldType) fieldType); + if (indexVersionCreated.onOrAfter(Version.V_5_0_0_alpha6)) { + throw new QueryShardException(context, "[{}] queries are no longer supported for geo_point field types. " + + "Use geo_distance sort or aggregations", NAME); + } else if (indexVersionCreated.before(Version.V_2_2_0)) { + LegacyGeoPointFieldType geoFieldType = (LegacyGeoPointFieldType) fieldType; IndexGeoPointFieldData indexFieldData = context.getForField(fieldType); String bboxOptimization = Strings.isEmpty(optimizeBbox) ? DEFAULT_OPTIMIZE_BBOX : optimizeBbox; return new GeoDistanceRangeQuery(point, fromValue, toValue, includeLower, includeUpper, geoDistance, geoFieldType, diff --git a/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java b/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java index 57a189b72f..ab3b23af0f 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java @@ -36,6 +36,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser.Token; import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; +import org.elasticsearch.index.mapper.LatLonPointFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import java.io.IOException; @@ -83,7 +84,7 @@ public class GeohashCellQuery { * @param geohashes optional array of additional geohashes * @return a new GeoBoundinboxfilter */ - public static Query create(QueryShardContext context, BaseGeoPointFieldMapper.GeoPointFieldType fieldType, + public static Query create(QueryShardContext context, BaseGeoPointFieldMapper.LegacyGeoPointFieldType fieldType, String geohash, @Nullable List<CharSequence> geohashes) { MappedFieldType geoHashMapper = fieldType.geoHashFieldType(); if (geoHashMapper == null) { @@ -241,11 +242,14 @@ public class GeohashCellQuery { } } - if (!(fieldType instanceof BaseGeoPointFieldMapper.GeoPointFieldType)) { + if (fieldType instanceof LatLonPointFieldMapper.LatLonPointFieldType) { + throw new QueryShardException(context, "failed to parse [{}] query. " + + "geo_point field no longer supports geohash_cell queries", NAME); + } else if (!(fieldType instanceof BaseGeoPointFieldMapper.LegacyGeoPointFieldType)) { throw new QueryShardException(context, "failed to parse [{}] query. field [{}] is not a geo_point field", NAME, fieldName); } - BaseGeoPointFieldMapper.GeoPointFieldType geoFieldType = ((BaseGeoPointFieldMapper.GeoPointFieldType) fieldType); + BaseGeoPointFieldMapper.LegacyGeoPointFieldType geoFieldType = ((BaseGeoPointFieldMapper.LegacyGeoPointFieldType) fieldType); if (!geoFieldType.isGeoHashPrefixEnabled()) { throw new QueryShardException(context, "failed to parse [{}] query. [geohash_prefix] is not enabled for field [{}]", NAME, fieldName); diff --git a/core/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeQuery.java b/core/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeQuery.java index 53cdf5861a..823f882f40 100644 --- a/core/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeQuery.java +++ b/core/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeQuery.java @@ -35,6 +35,7 @@ import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.index.fielddata.IndexGeoPointFieldData; import org.elasticsearch.index.fielddata.MultiGeoPointValues; +import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; import org.elasticsearch.index.mapper.LegacyGeoPointFieldMapper; import java.io.IOException; @@ -60,7 +61,8 @@ public class GeoDistanceRangeQuery extends Query { private final IndexGeoPointFieldData indexFieldData; public GeoDistanceRangeQuery(GeoPoint point, Double lowerVal, Double upperVal, boolean includeLower, - boolean includeUpper, GeoDistance geoDistance, LegacyGeoPointFieldMapper.GeoPointFieldType fieldType, + boolean includeUpper, GeoDistance geoDistance, + LegacyGeoPointFieldMapper.LegacyGeoPointFieldType fieldType, IndexGeoPointFieldData indexFieldData, String optimizeBbox) { this.lat = point.lat(); this.lon = point.lon(); diff --git a/core/src/main/java/org/elasticsearch/index/search/geo/LegacyIndexedGeoBoundingBoxQuery.java b/core/src/main/java/org/elasticsearch/index/search/geo/LegacyIndexedGeoBoundingBoxQuery.java index f60a12f023..6fdb2a906c 100644 --- a/core/src/main/java/org/elasticsearch/index/search/geo/LegacyIndexedGeoBoundingBoxQuery.java +++ b/core/src/main/java/org/elasticsearch/index/search/geo/LegacyIndexedGeoBoundingBoxQuery.java @@ -33,7 +33,8 @@ import org.elasticsearch.index.mapper.LegacyGeoPointFieldMapper; @Deprecated public class LegacyIndexedGeoBoundingBoxQuery { - public static Query create(GeoPoint topLeft, GeoPoint bottomRight, LegacyGeoPointFieldMapper.GeoPointFieldType fieldType) { + public static Query create(GeoPoint topLeft, GeoPoint bottomRight, + LegacyGeoPointFieldMapper.LegacyGeoPointFieldType fieldType) { if (!fieldType.isLatLonEnabled()) { throw new IllegalArgumentException("lat/lon is not enabled (indexed) for field [" + fieldType.name() + "], can't use indexed filter on it"); @@ -47,7 +48,7 @@ public class LegacyIndexedGeoBoundingBoxQuery { } private static Query westGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, - LegacyGeoPointFieldMapper.GeoPointFieldType fieldType) { + LegacyGeoPointFieldMapper.LegacyGeoPointFieldType fieldType) { BooleanQuery.Builder filter = new BooleanQuery.Builder(); filter.setMinimumNumberShouldMatch(1); filter.add(fieldType.lonFieldType().rangeQuery(null, bottomRight.lon(), true, true), Occur.SHOULD); @@ -57,7 +58,7 @@ public class LegacyIndexedGeoBoundingBoxQuery { } private static Query eastGeoBoundingBoxFilter(GeoPoint topLeft, GeoPoint bottomRight, - LegacyGeoPointFieldMapper.GeoPointFieldType fieldType) { + LegacyGeoPointFieldMapper.LegacyGeoPointFieldType fieldType) { BooleanQuery.Builder filter = new BooleanQuery.Builder(); filter.add(fieldType.lonFieldType().rangeQuery(topLeft.lon(), bottomRight.lon(), true, true), Occur.MUST); filter.add(fieldType.latFieldType().rangeQuery(bottomRight.lat(), topLeft.lat(), true, true), Occur.MUST); diff --git a/core/src/main/java/org/elasticsearch/indices/IndicesModule.java b/core/src/main/java/org/elasticsearch/indices/IndicesModule.java index fed710244f..eb1843dc7d 100644 --- a/core/src/main/java/org/elasticsearch/indices/IndicesModule.java +++ b/core/src/main/java/org/elasticsearch/indices/IndicesModule.java @@ -36,23 +36,24 @@ import org.elasticsearch.index.mapper.DateFieldMapper; import org.elasticsearch.index.mapper.FieldNamesFieldMapper; import org.elasticsearch.index.mapper.GeoPointFieldMapper; import org.elasticsearch.index.mapper.GeoShapeFieldMapper; -import org.elasticsearch.index.mapper.IdFieldMapper; -import org.elasticsearch.index.mapper.IndexFieldMapper; import org.elasticsearch.index.mapper.IpFieldMapper; import org.elasticsearch.index.mapper.KeywordFieldMapper; +import org.elasticsearch.index.mapper.LatLonPointFieldMapper; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.MetadataFieldMapper; import org.elasticsearch.index.mapper.NumberFieldMapper; import org.elasticsearch.index.mapper.ObjectMapper; +import org.elasticsearch.index.mapper.TextFieldMapper; +import org.elasticsearch.index.mapper.TokenCountFieldMapper; +import org.elasticsearch.index.mapper.ScaledFloatFieldMapper; +import org.elasticsearch.index.mapper.StringFieldMapper; +import org.elasticsearch.index.mapper.IdFieldMapper; +import org.elasticsearch.index.mapper.IndexFieldMapper; import org.elasticsearch.index.mapper.ParentFieldMapper; import org.elasticsearch.index.mapper.RoutingFieldMapper; -import org.elasticsearch.index.mapper.ScaledFloatFieldMapper; import org.elasticsearch.index.mapper.SourceFieldMapper; -import org.elasticsearch.index.mapper.StringFieldMapper; -import org.elasticsearch.index.mapper.TTLFieldMapper; -import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.index.mapper.TimestampFieldMapper; -import org.elasticsearch.index.mapper.TokenCountFieldMapper; +import org.elasticsearch.index.mapper.TTLFieldMapper; import org.elasticsearch.index.mapper.TypeFieldMapper; import org.elasticsearch.index.mapper.UidFieldMapper; import org.elasticsearch.index.mapper.VersionFieldMapper; @@ -119,6 +120,7 @@ public class IndicesModule extends AbstractModule { mappers.put(ObjectMapper.NESTED_CONTENT_TYPE, new ObjectMapper.TypeParser()); mappers.put(CompletionFieldMapper.CONTENT_TYPE, new CompletionFieldMapper.TypeParser()); mappers.put(GeoPointFieldMapper.CONTENT_TYPE, new GeoPointFieldMapper.TypeParser()); + mappers.put(LatLonPointFieldMapper.CONTENT_TYPE, new LatLonPointFieldMapper.TypeParser()); if (ShapesAvailability.JTS_AVAILABLE && ShapesAvailability.SPATIAL4J_AVAILABLE) { mappers.put(GeoShapeFieldMapper.CONTENT_TYPE, new GeoShapeFieldMapper.TypeParser()); } diff --git a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java index 854a5fb0e1..bd1449bbfe 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/completion/context/GeoContextMapping.java @@ -207,7 +207,8 @@ public class GeoContextMapping extends ContextMapping<GeoQueryContext> { if (field instanceof StringField) { spare.resetFromString(field.stringValue()); } else { - spare.resetFromIndexHash(Long.parseLong(field.stringValue())); + // todo return this to .stringValue() once LatLonPoint implements it + spare.resetFromIndexableField(field); } geohashes.add(spare.geohash()); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java b/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java index a36f618871..55f6b0b52c 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java @@ -293,7 +293,7 @@ public class DocumentParserTests extends ESSingleNodeTestCase { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startArray("dynamic_templates").startObject().startObject("georule") .field("match", "foo*") - .startObject("mapping").field("type", "geo_point").endObject() + .startObject("mapping").field("type", "geo_point").field("doc_values", false).endObject() .endObject().endObject().endArray().endObject().endObject().string(); DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); @@ -373,7 +373,7 @@ public class DocumentParserTests extends ESSingleNodeTestCase { public void testMappedGeoPointArray() throws Exception { DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("foo").field("type", "geo_point") + .startObject("properties").startObject("foo").field("type", "geo_point").field("doc_values", false) .endObject().endObject().endObject().endObject().string(); DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/ExternalFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/ExternalFieldMapperTests.java index 6f76b1c59b..4a019ad166 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/ExternalFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/ExternalFieldMapperTests.java @@ -25,6 +25,7 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.Version; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.compress.CompressedXContent; +import org.elasticsearch.common.geo.GeoHashUtils; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.IndexService; @@ -83,7 +84,7 @@ public class ExternalFieldMapperTests extends ESSingleNodeTestCase { assertThat(doc.rootDoc().getField("field.point"), notNullValue()); if (version.before(Version.V_2_2_0)) { assertThat(doc.rootDoc().getField("field.point").stringValue(), is("42.0,51.0")); - } else { + } else if (version.after(Version.V_5_0_0_alpha6)) { assertThat(Long.parseLong(doc.rootDoc().getField("field.point").stringValue()), is(GeoPointField.encodeLatLon(42.0, 51.0))); } @@ -141,7 +142,7 @@ public class ExternalFieldMapperTests extends ESSingleNodeTestCase { assertThat(doc.rootDoc().getField("field.point"), notNullValue()); if (version.before(Version.V_2_2_0)) { assertThat(doc.rootDoc().getField("field.point").stringValue(), is("42.0,51.0")); - } else { + } else if (version.after(Version.V_5_0_0_alpha6)) { assertThat(Long.parseLong(doc.rootDoc().getField("field.point").stringValue()), is(GeoPointField.encodeLatLon(42.0, 51.0))); } @@ -211,7 +212,7 @@ public class ExternalFieldMapperTests extends ESSingleNodeTestCase { assertThat(doc.rootDoc().getField("field.point"), notNullValue()); if (version.before(Version.V_2_2_0)) { assertThat(doc.rootDoc().getField("field.point").stringValue(), is("42.0,51.0")); - } else { + } else if (version.before(Version.V_5_0_0_alpha6)) { assertThat(Long.parseLong(doc.rootDoc().getField("field.point").stringValue()), is(GeoPointField.encodeLatLon(42.0, 51.0))); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java b/core/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java index 2e75124c29..c8d9899206 100755 --- a/core/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/ExternalMapper.java @@ -59,6 +59,7 @@ public class ExternalMapper extends FieldMapper { private BooleanFieldMapper.Builder boolBuilder = new BooleanFieldMapper.Builder(Names.FIELD_BOOL); private GeoPointFieldMapper.Builder pointBuilder = new GeoPointFieldMapper.Builder(Names.FIELD_POINT); private LegacyGeoPointFieldMapper.Builder legacyPointBuilder = new LegacyGeoPointFieldMapper.Builder(Names.FIELD_POINT); + private LatLonPointFieldMapper.Builder latLonPointBuilder = new LatLonPointFieldMapper.Builder(Names.FIELD_POINT); private GeoShapeFieldMapper.Builder shapeBuilder = new GeoShapeFieldMapper.Builder(Names.FIELD_SHAPE); private Mapper.Builder stringBuilder; private String generatedValue; @@ -82,8 +83,14 @@ public class ExternalMapper extends FieldMapper { context.path().add(name); BinaryFieldMapper binMapper = binBuilder.build(context); BooleanFieldMapper boolMapper = boolBuilder.build(context); - BaseGeoPointFieldMapper pointMapper = (context.indexCreatedVersion().before(Version.V_2_2_0)) ? - legacyPointBuilder.build(context) : pointBuilder.build(context); + BaseGeoPointFieldMapper pointMapper; + if (context.indexCreatedVersion().before(Version.V_2_2_0)) { + pointMapper = legacyPointBuilder.build(context); + } else if (context.indexCreatedVersion().onOrAfter(Version.V_5_0_0_alpha6)) { + pointMapper = latLonPointBuilder.build(context); + } else { + pointMapper = pointBuilder.build(context); + } GeoShapeFieldMapper shapeMapper = shapeBuilder.build(context); FieldMapper stringMapper = (FieldMapper)stringBuilder.build(context); context.path().remove(); @@ -198,7 +205,7 @@ public class ExternalMapper extends FieldMapper { MultiFields multiFieldsUpdate = multiFields.updateFieldType(fullNameToFieldType); BinaryFieldMapper binMapperUpdate = (BinaryFieldMapper) binMapper.updateFieldType(fullNameToFieldType); BooleanFieldMapper boolMapperUpdate = (BooleanFieldMapper) boolMapper.updateFieldType(fullNameToFieldType); - GeoPointFieldMapper pointMapperUpdate = (GeoPointFieldMapper) pointMapper.updateFieldType(fullNameToFieldType); + BaseGeoPointFieldMapper pointMapperUpdate = (BaseGeoPointFieldMapper) pointMapper.updateFieldType(fullNameToFieldType); GeoShapeFieldMapper shapeMapperUpdate = (GeoShapeFieldMapper) shapeMapper.updateFieldType(fullNameToFieldType); TextFieldMapper stringMapperUpdate = (TextFieldMapper) stringMapper.updateFieldType(fullNameToFieldType); if (update == this diff --git a/core/src/test/java/org/elasticsearch/index/mapper/ExternalValuesMapperIntegrationIT.java b/core/src/test/java/org/elasticsearch/index/mapper/ExternalValuesMapperIntegrationIT.java index 342fa247d7..c75871e43b 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/ExternalValuesMapperIntegrationIT.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/ExternalValuesMapperIntegrationIT.java @@ -112,7 +112,7 @@ public class ExternalValuesMapperIntegrationIT extends ESIntegTestCase { assertThat(response.getHits().totalHits(), equalTo((long) 1)); response = client().prepareSearch("test-idx") - .setPostFilter(QueryBuilders.geoDistanceRangeQuery("field.point", 42.0, 51.0).to("1km")) + .setPostFilter(QueryBuilders.geoDistanceQuery("field.point").point(42.0, 51.0).distance("1km")) .execute().actionGet(); assertThat(response.getHits().totalHits(), equalTo((long) 1)); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java index b5256761f6..a289ee3b2d 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldMapperTests.java @@ -18,7 +18,6 @@ */ package org.elasticsearch.index.mapper; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.spatial.geopoint.document.GeoPointField; import org.apache.lucene.util.BytesRef; import org.elasticsearch.Version; @@ -31,17 +30,13 @@ import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.DocumentMapperParser; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.search.SearchHitField; import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.InternalSettingsPlugin; import org.elasticsearch.test.VersionUtils; import org.elasticsearch.test.geo.RandomGeoGenerator; +import org.hamcrest.CoreMatchers; import java.util.Collection; import java.util.List; @@ -67,12 +62,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { return pluginList(InternalSettingsPlugin.class); } - public void testLatLonValues() throws Exception { + public void testLegacyLatLonValues() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).endObject().endObject() .endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -96,13 +91,13 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } } - public void testLatLonValuesWithGeohash() throws Exception { + public void testLegacyLatLonValuesWithGeohash() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) .field("geohash", true).endObject().endObject() .endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -121,12 +116,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } } - public void testLatLonInOneValueWithGeohash() throws Exception { + public void testLegacyLatLonInOneValueWithGeohash() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) .field("geohash", true).endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -145,12 +140,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } } - public void testGeoHashIndexValue() throws Exception { + public void testLegacyGeoHashIndexValue() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) .field("geohash", true).endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -170,11 +165,13 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } public void testGeoHashValue() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -184,13 +181,15 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - assertThat(doc.rootDoc().get("point"), notNullValue()); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + } } - public void testNormalizeLatLonValuesDefault() throws Exception { - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + public void testNormalizeLegacyLatLonValuesDefault() throws Exception { + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); // default to normalize XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point"); @@ -239,8 +238,8 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } } - public void testValidateLatLonValues() throws Exception { - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + public void testLegacyValidateLatLonValues() throws Exception { + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true); if (version.before(Version.V_2_2_0)) { @@ -338,8 +337,8 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } } - public void testNoValidateLatLonValues() throws Exception { - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + public void testNoValidateLegacyLatLonValues() throws Exception { + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true); if (version.before(Version.V_2_2_0)) { @@ -400,11 +399,13 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } public void testLatLonValuesStored() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .field("store", true).endObject().endObject().endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.CURRENT, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.field("store", true).endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -414,24 +415,30 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lat").numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon").numericValue().doubleValue(), equalTo(1.3)); - assertThat(doc.rootDoc().getField("point.geohash"), nullValue()); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().get("point")), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + // TODO LatLonPoint FieldType is private and frozen, need to add ability to store field + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lat").numericValue().doubleValue(), equalTo(1.2)); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon").numericValue().doubleValue(), equalTo(1.3)); + assertThat(doc.rootDoc().getField("point.geohash"), nullValue()); + if (version.before(Version.V_2_2_0)) { + assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); + } else { + assertThat(Long.parseLong(doc.rootDoc().get("point")), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + } } } public void testArrayLatLonValues() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .field("store", true).endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("doc_values", false); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.field("store", true).endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -444,28 +451,10 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - if (version.onOrAfter(Version.V_5_0_0_alpha2)) { - assertThat(doc.rootDoc().getFields("point.lat").length, equalTo(4)); - assertThat(doc.rootDoc().getFields("point.lon").length, equalTo(4)); - - // point field for 1st value - assertThat(doc.rootDoc().getFields("point.lat")[0].numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getFields("point.lon")[0].numericValue().doubleValue(), equalTo(1.3)); - // stored field for 1st value - assertThat(doc.rootDoc().getFields("point.lat")[1].numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getFields("point.lon")[1].numericValue().doubleValue(), equalTo(1.3)); - // indexed hash - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); - - // point field for 2nd value - assertThat(doc.rootDoc().getFields("point.lat")[2].numericValue().doubleValue(), equalTo(1.4)); - assertThat(doc.rootDoc().getFields("point.lon")[2].numericValue().doubleValue(), equalTo(1.5)); - // stored field for 2nd value - assertThat(doc.rootDoc().getFields("point.lat")[3].numericValue().doubleValue(), equalTo(1.4)); - assertThat(doc.rootDoc().getFields("point.lon")[3].numericValue().doubleValue(), equalTo(1.5)); - // indexed hash - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[1].stringValue()), equalTo(GeoPointField.encodeLatLon(1.4, 1.5))); - } else { + // doc values are enabled by default, but in this test we disable them; we should only have 2 points + assertThat(doc.rootDoc().getFields("point"), notNullValue()); + assertThat(doc.rootDoc().getFields("point").length, equalTo(2)); + if (version.before(Version.V_5_0_0_alpha2)) { assertThat(doc.rootDoc().getFields("point.lat").length, equalTo(2)); assertThat(doc.rootDoc().getFields("point.lon").length, equalTo(2)); assertThat(doc.rootDoc().getFields("point.lat")[0].numericValue().doubleValue(), equalTo(1.2)); @@ -486,13 +475,16 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } public void testLatLonInOneValue() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); + DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", + new CompressedXContent(mapping)); ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() .startObject() @@ -500,49 +492,61 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + if (version.before(Version.V_2_2_0)) { + assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); + } else { + assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + } } } public void testLatLonInOneValueStored() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("store", true).endObject().endObject() - .endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.field("store", true).endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); + DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", + new CompressedXContent(mapping)); ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() .startObject() .field("point", "1.2,1.3") .endObject() .bytes()); - - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lat").numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon").numericValue().doubleValue(), equalTo(1.3)); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lat").numericValue().doubleValue(), equalTo(1.2)); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon").numericValue().doubleValue(), equalTo(1.3)); + if (version.before(Version.V_2_2_0)) { + assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); + } else { + assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), + equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + } } } public void testLatLonInOneValueArray() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .field("store", true).endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("doc_values", false); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.field("store", true).endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); + DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", + new CompressedXContent(mapping)); ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() .startObject() @@ -553,6 +557,9 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); + // doc values are enabled by default, but in this test we disable them; we should only have 2 points + assertThat(doc.rootDoc().getFields("point"), notNullValue()); + assertThat(doc.rootDoc().getFields("point").length, equalTo(2)); if (version.before(Version.V_5_0_0_alpha2)) { assertThat(doc.rootDoc().getFields("point.lat").length, equalTo(2)); assertThat(doc.rootDoc().getFields("point.lon").length, equalTo(2)); @@ -560,34 +567,27 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { assertThat(doc.rootDoc().getFields("point.lon")[0].numericValue().doubleValue(), equalTo(1.3)); assertThat(doc.rootDoc().getFields("point.lat")[1].numericValue().doubleValue(), equalTo(1.4)); assertThat(doc.rootDoc().getFields("point.lon")[1].numericValue().doubleValue(), equalTo(1.5)); - } else { - IndexableField[] latPoints = doc.rootDoc().getFields("point.lat"); - IndexableField[] lonPoints = doc.rootDoc().getFields("point.lon"); - assertThat(latPoints.length, equalTo(4)); - assertThat(lonPoints.length, equalTo(4)); - assertThat(latPoints[0].numericValue().doubleValue(), equalTo(1.2)); - assertThat(lonPoints[0].numericValue().doubleValue(), equalTo(1.3)); - assertThat(latPoints[2].numericValue().doubleValue(), equalTo(1.4)); - assertThat(lonPoints[2].numericValue().doubleValue(), equalTo(1.5)); } if (version.before(Version.V_2_2_0)) { assertThat(doc.rootDoc().getFields("point")[0].stringValue(), equalTo("1.2,1.3")); - } else { + } else if (version.before(Version.V_5_0_0_alpha6)) { assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); } if (version.before(Version.V_2_2_0)) { assertThat(doc.rootDoc().getFields("point")[1].stringValue(), equalTo("1.4,1.5")); - } else { + } else if (version.before(Version.V_5_0_0_alpha6)) { assertThat(Long.parseLong(doc.rootDoc().getFields("point")[1].stringValue()), equalTo(GeoPointField.encodeLatLon(1.4, 1.5))); } } public void testLonLatArray() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).endObject().endObject() - .endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -597,22 +597,27 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + if (version.before(Version.V_2_2_0)) { + assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); + } else { + assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + } } } public void testLonLatArrayDynamic() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startArray("dynamic_templates").startObject() - .startObject("point").field("match", "point*").startObject("mapping").field("type", "geo_point") - .field("lat_lon", true).endObject().endObject().endObject().endArray().endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.CURRENT, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startArray("dynamic_templates").startObject().startObject("point").field("match", "point*") + .startObject("mapping").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.endObject().endObject().endObject().endArray().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -622,21 +627,26 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + if (version.before(Version.V_2_2_0)) { + assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); + } else { + assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + } } } public void testLonLatArrayStored() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .field("store", true).endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.field("store", true).endObject().endObject().endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -646,23 +656,29 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lat").numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); - assertThat(doc.rootDoc().getField("point.lon").numericValue().doubleValue(), equalTo(1.3)); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + assertThat(doc.rootDoc().getField("point"), notNullValue()); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(doc.rootDoc().getField("point.lat"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lat").numericValue().doubleValue(), equalTo(1.2)); + assertThat(doc.rootDoc().getField("point.lon"), notNullValue()); + assertThat(doc.rootDoc().getField("point.lon").numericValue().doubleValue(), equalTo(1.3)); + if (version.before(Version.V_2_2_0)) { + assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); + } else { + assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); + } } } public void testLonLatArrayArrayStored() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) - .field("store", true).endObject().endObject().endObject().endObject().string(); - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true); + } + String mapping = xContentBuilder.field("store", true).field("doc_values", false).endObject().endObject() + .endObject().endObject().string(); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); @@ -675,6 +691,8 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); + assertThat(doc.rootDoc().getFields("point"), notNullValue()); + assertThat(doc.rootDoc().getFields("point").length, CoreMatchers.equalTo(2)); if (version.before(Version.V_5_0_0_alpha2)) { assertThat(doc.rootDoc().getFields("point.lat").length, equalTo(2)); assertThat(doc.rootDoc().getFields("point.lon").length, equalTo(2)); @@ -692,19 +710,6 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } else { assertThat(Long.parseLong(doc.rootDoc().getFields("point")[1].stringValue()), equalTo(GeoPointField.encodeLatLon(1.4, 1.5))); } - } else { - assertThat(doc.rootDoc().getFields("point.lat").length, equalTo(4)); - assertThat(doc.rootDoc().getFields("point.lon").length, equalTo(4)); - assertThat(doc.rootDoc().getFields("point.lat")[0].numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getFields("point.lat")[1].numericValue().doubleValue(), equalTo(1.2)); - assertThat(doc.rootDoc().getFields("point.lon")[0].numericValue().doubleValue(), equalTo(1.3)); - assertThat(doc.rootDoc().getFields("point.lon")[1].numericValue().doubleValue(), equalTo(1.3)); - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[0].stringValue()), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); - assertThat(doc.rootDoc().getFields("point.lat")[2].numericValue().doubleValue(), equalTo(1.4)); - assertThat(doc.rootDoc().getFields("point.lat")[3].numericValue().doubleValue(), equalTo(1.4)); - assertThat(doc.rootDoc().getFields("point.lon")[2].numericValue().doubleValue(), equalTo(1.5)); - assertThat(doc.rootDoc().getFields("point.lon")[3].numericValue().doubleValue(), equalTo(1.5)); - assertThat(Long.parseLong(doc.rootDoc().getFields("point")[1].stringValue()), equalTo(GeoPointField.encodeLatLon(1.4, 1.5))); } } @@ -717,11 +722,35 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); DocumentMapperParser parser = createIndex("test", settings).mapperService().documentMapperParser(); // test deprecation exceptions on newly created indexes - try { - String validateMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("geohash", true) - .field("validate", true).endObject().endObject() + if (version.onOrAfter(Version.V_5_0_0_alpha6)) { + try { + String normalizeMapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).endObject().endObject() + .endObject().endObject().string(); + parser.parse("type", new CompressedXContent(normalizeMapping)); + } catch (MapperParsingException e) { + assertEquals(e.getMessage(), "Mapping definition for [point] has unsupported parameters: [lat_lon : true]"); + } + } + + if (version.onOrAfter(Version.V_5_0_0_alpha6)) { + try { + String normalizeMapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true).endObject().endObject() .endObject().endObject().string(); + parser.parse("type", new CompressedXContent(normalizeMapping)); + } catch (MapperParsingException e) { + assertEquals(e.getMessage(), "Mapping definition for [point] has unsupported parameters: [geohash : true]"); + } + } + + try { + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true).field("geohash", true); + } + String validateMapping = xContentBuilder.field("validate", true).endObject().endObject().endObject().endObject().string(); parser.parse("type", new CompressedXContent(validateMapping)); fail("process completed successfully when " + MapperParsingException.class.getName() + " expected"); } catch (MapperParsingException e) { @@ -729,10 +758,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } try { - String validateMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("geohash", true) - .field("validate_lat", true).endObject().endObject() - .endObject().endObject().string(); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true).field("geohash", true); + } + String validateMapping = xContentBuilder.field("validate_lat", true).endObject().endObject().endObject().endObject().string(); parser.parse("type", new CompressedXContent(validateMapping)); fail("process completed successfully when " + MapperParsingException.class.getName() + " expected"); } catch (MapperParsingException e) { @@ -740,10 +771,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } try { - String validateMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("geohash", true) - .field("validate_lon", true).endObject().endObject() - .endObject().endObject().string(); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true).field("geohash", true); + } + String validateMapping = xContentBuilder.field("validate_lon", true).endObject().endObject().endObject().endObject().string(); parser.parse("type", new CompressedXContent(validateMapping)); fail("process completed successfully when " + MapperParsingException.class.getName() + " expected"); } catch (MapperParsingException e) { @@ -752,10 +785,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { // test deprecated normalize try { - String normalizeMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("geohash", true) - .field("normalize", true).endObject().endObject() - .endObject().endObject().string(); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true).field("geohash", true); + } + String normalizeMapping = xContentBuilder.field("normalize", true).endObject().endObject().endObject().endObject().string(); parser.parse("type", new CompressedXContent(normalizeMapping)); fail("process completed successfully when " + MapperParsingException.class.getName() + " expected"); } catch (MapperParsingException e) { @@ -763,10 +798,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } try { - String normalizeMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("geohash", true) - .field("normalize_lat", true).endObject().endObject() - .endObject().endObject().string(); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true).field("geohash", true); + } + String normalizeMapping = xContentBuilder.field("normalize_lat", true).endObject().endObject().endObject().endObject().string(); parser.parse("type", new CompressedXContent(normalizeMapping)); fail("process completed successfully when " + MapperParsingException.class.getName() + " expected"); } catch (MapperParsingException e) { @@ -774,10 +811,12 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } try { - String normalizeMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true).field("geohash", true) - .field("normalize_lon", true).endObject().endObject() - .endObject().endObject().string(); + XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point"); + if (version.before(Version.V_5_0_0_alpha6)) { + xContentBuilder = xContentBuilder.field("lat_lon", true).field("geohash", true); + } + String normalizeMapping = xContentBuilder.field("normalize_lon", true).endObject().endObject().endObject().endObject().string(); parser.parse("type", new CompressedXContent(normalizeMapping)); fail("process completed successfully when " + MapperParsingException.class.getName() + " expected"); } catch (MapperParsingException e) { @@ -785,8 +824,8 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { } } - public void testGeoPointMapperMerge() throws Exception { - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + public void testLegacyGeoPointMapperMerge() throws Exception { + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); String stage1Mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", true) @@ -812,7 +851,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { mapperService.merge("type", new CompressedXContent(stage2Mapping), MapperService.MergeReason.MAPPING_UPDATE, false); } - public void testGeoHashSearch() throws Exception { + public void testLegacyGeoHashSearch() throws Exception { // create a geo_point mapping with geohash enabled and random (between 1 and 12) geohash precision int precision = randomIntBetween(1, 12); String mapping = XContentFactory.jsonBuilder().startObject().startObject("pin").startObject("properties").startObject("location") @@ -820,7 +859,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject().endObject().endObject().string(); // create index and add a test point (dr5regy6rc6z) - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha1); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); CreateIndexRequestBuilder mappingRequest = client().admin().indices().prepareCreate("test").setSettings(settings) .addMapping("pin", mapping); @@ -837,7 +876,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { assertEquals("dr5regy6rc6y".substring(0, precision), m.get("location.geohash").value()); } - public void testGeoHashSearchWithPrefix() throws Exception { + public void testLegacyGeoHashSearchWithPrefix() throws Exception { // create a geo_point mapping with geohash enabled and random (between 1 and 12) geohash precision int precision = randomIntBetween(1, 12); String mapping = XContentFactory.jsonBuilder().startObject().startObject("pin").startObject("properties").startObject("location") @@ -845,7 +884,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .endObject().endObject().endObject().endObject().string(); // create index and add a test point (dr5regy6rc6z) - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); CreateIndexRequestBuilder mappingRequest = client().admin().indices().prepareCreate("test").setSettings(settings) .addMapping("pin", mapping); @@ -870,9 +909,11 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { public void testMultiField() throws Exception { int numDocs = randomIntBetween(10, 100); String mapping = XContentFactory.jsonBuilder().startObject().startObject("pin").startObject("properties").startObject("location") - .field("type", "geo_point").startObject("fields") - .startObject("geohash").field("type", "geo_point").field("geohash_precision", 12).field("geohash_prefix", true).endObject() - .startObject("latlon").field("type", "geo_point").field("lat_lon", true).endObject().endObject() + .field("type", "geo_point") + .startObject("fields") + .startObject("geohash").field("type", "keyword").endObject() // test geohash as keyword + .startObject("latlon").field("type", "string").endObject() // test geohash as string + .endObject() .endObject().endObject().endObject().endObject().string(); CreateIndexRequestBuilder mappingRequest = client().admin().indices().prepareCreate("test") .addMapping("pin", mapping); @@ -886,6 +927,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { .field("lon", pt.lon()).endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); } + // TODO these tests are bogus and need to be Fix // query by geohash subfield SearchResponse searchResponse = client().prepareSearch().addStoredField("location.geohash").setQuery(matchAllQuery()).execute().actionGet(); assertEquals(numDocs, searchResponse.getHits().totalHits()); @@ -899,7 +941,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase { public void testEmptyName() throws Exception { // after 5.x String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("").field("type", "geo_point").field("lat_lon", true).endObject().endObject() + .startObject("properties").startObject("").field("type", "geo_point").endObject().endObject() .endObject().endObject().string(); Version version = Version.CURRENT; diff --git a/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldTypeTests.java b/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldTypeTests.java index 6e6222ac87..fac30002fb 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldTypeTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/GeoPointFieldTypeTests.java @@ -18,16 +18,13 @@ */ package org.elasticsearch.index.mapper; -import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; -import org.elasticsearch.index.mapper.LegacyDoubleFieldMapper; -import org.elasticsearch.index.mapper.MappedFieldType; -import org.elasticsearch.index.mapper.StringFieldMapper; +import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper.LegacyGeoPointFieldType; import org.junit.Before; public class GeoPointFieldTypeTests extends FieldTypeTestCase { @Override protected MappedFieldType createDefaultFieldType() { - return new BaseGeoPointFieldMapper.GeoPointFieldType(); + return new LegacyGeoPointFieldType(); } @Before @@ -35,13 +32,14 @@ public class GeoPointFieldTypeTests extends FieldTypeTestCase { addModifier(new Modifier("geohash", false) { @Override public void modify(MappedFieldType ft) { - ((BaseGeoPointFieldMapper.GeoPointFieldType)ft).setGeoHashEnabled(new StringFieldMapper.StringFieldType(), 1, true); + ((LegacyGeoPointFieldType)ft).setGeoHashEnabled(new StringFieldMapper.StringFieldType(), 1, true); } }); addModifier(new Modifier("lat_lon", false) { @Override public void modify(MappedFieldType ft) { - ((BaseGeoPointFieldMapper.GeoPointFieldType)ft).setLatLonEnabled(new LegacyDoubleFieldMapper.DoubleFieldType(), new LegacyDoubleFieldMapper.DoubleFieldType()); + ((LegacyGeoPointFieldType)ft).setLatLonEnabled(new LegacyDoubleFieldMapper.DoubleFieldType(), + new LegacyDoubleFieldMapper.DoubleFieldType()); } }); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/GeohashMappingGeoPointTests.java b/core/src/test/java/org/elasticsearch/index/mapper/GeohashMappingGeoPointTests.java deleted file mode 100644 index 05581e7902..0000000000 --- a/core/src/test/java/org/elasticsearch/index/mapper/GeohashMappingGeoPointTests.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.index.mapper; - -import org.apache.lucene.spatial.geopoint.document.GeoPointField; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.Version; -import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.common.compress.CompressedXContent; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.FieldMapper; -import org.elasticsearch.index.mapper.ParsedDocument; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.test.ESSingleNodeTestCase; -import org.elasticsearch.test.InternalSettingsPlugin; -import org.elasticsearch.test.VersionUtils; - -import java.util.Collection; - -import static org.elasticsearch.common.geo.GeoHashUtils.stringEncode; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; - -/** - * - */ -public class GeohashMappingGeoPointTests extends ESSingleNodeTestCase { - - @Override - protected Collection<Class<? extends Plugin>> getPlugins() { - return pluginList(InternalSettingsPlugin.class); - } - - public void testLatLonValues() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", false) - .endObject().endObject().endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); - - ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() - .startObject() - .startObject("point").field("lat", 1.2).field("lon", 1.3).endObject() - .endObject() - .bytes()); - - assertThat(doc.rootDoc().getField("point.lat"), nullValue()); - assertThat(doc.rootDoc().getField("point.lon"), nullValue()); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().get("point")), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); - } - } - - public void testLatLonInOneValue() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("lat_lon", false).endObject().endObject() - .endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); - - ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() - .startObject() - .field("point", "1.2,1.3") - .endObject() - .bytes()); - - assertThat(doc.rootDoc().getField("point.lat"), nullValue()); - assertThat(doc.rootDoc().getField("point.lon"), nullValue()); - if (version.before(Version.V_2_2_0)) { - assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3")); - } else { - assertThat(Long.parseLong(doc.rootDoc().get("point")), equalTo(GeoPointField.encodeLatLon(1.2, 1.3))); - } - } - - public void testGeoHashValue() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true) - .endObject().endObject().endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); - - ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() - .startObject() - .field("point", stringEncode(1.3, 1.2)) - .endObject() - .bytes()); - - assertThat(doc.rootDoc().getField("point.lat"), nullValue()); - assertThat(doc.rootDoc().getField("point.lon"), nullValue()); - assertThat(doc.rootDoc().getBinaryValue("point.geohash"), equalTo(new BytesRef(stringEncode(1.3, 1.2)))); - assertThat(doc.rootDoc().get("point"), notNullValue()); - } - - public void testGeoHashPrecisionAsInteger() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true) - .field("geohash_precision", 10).endObject().endObject().endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); - FieldMapper mapper = defaultMapper.mappers().smartNameFieldMapper("point"); - assertThat(mapper, instanceOf(BaseGeoPointFieldMapper.class)); - BaseGeoPointFieldMapper geoPointFieldMapper = (BaseGeoPointFieldMapper) mapper; - assertThat(geoPointFieldMapper.fieldType().geoHashPrecision(), is(10)); - } - - public void testGeoHashPrecisionAsLength() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true).field("geohash_precision", "5m").endObject().endObject() - .endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); - FieldMapper mapper = defaultMapper.mappers().smartNameFieldMapper("point"); - assertThat(mapper, instanceOf(BaseGeoPointFieldMapper.class)); - BaseGeoPointFieldMapper geoPointFieldMapper = (BaseGeoPointFieldMapper) mapper; - assertThat(geoPointFieldMapper.fieldType().geoHashPrecision(), is(10)); - } - - public void testNullValue() throws Exception { - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("properties").startObject("point").field("type", "geo_point").endObject().endObject() - .endObject().endObject().string(); - - Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.CURRENT); - Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); - - ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() - .startObject() - .field("point", (Object) null) - .endObject() - .bytes()); - - assertThat(doc.rootDoc().get("point"), nullValue()); - } -} diff --git a/core/src/test/java/org/elasticsearch/index/mapper/LegacyGeohashMappingGeoPointTests.java b/core/src/test/java/org/elasticsearch/index/mapper/LegacyGeohashMappingGeoPointTests.java new file mode 100644 index 0000000000..c5e99b4385 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/index/mapper/LegacyGeohashMappingGeoPointTests.java @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.index.mapper; + +import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.common.compress.CompressedXContent; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper.LegacyGeoPointFieldType; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESSingleNodeTestCase; +import org.elasticsearch.test.InternalSettingsPlugin; +import org.elasticsearch.test.VersionUtils; + +import java.util.Collection; + +import static org.elasticsearch.common.geo.GeoHashUtils.stringEncode; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; + +/** + * + */ +public class LegacyGeohashMappingGeoPointTests extends ESSingleNodeTestCase { + + @Override + protected Collection<Class<? extends Plugin>> getPlugins() { + return pluginList(InternalSettingsPlugin.class); + } + + public void testGeoHashValue() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true) + .endObject().endObject().endObject().endObject().string(); + + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); + Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); + DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser() + .parse("type", new CompressedXContent(mapping)); + + ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() + .startObject() + .field("point", stringEncode(1.3, 1.2)) + .endObject() + .bytes()); + + assertThat(doc.rootDoc().getField("point.lat"), nullValue()); + assertThat(doc.rootDoc().getField("point.lon"), nullValue()); + assertThat(doc.rootDoc().get("point.geohash"), equalTo(stringEncode(1.3, 1.2))); + assertThat(doc.rootDoc().get("point"), notNullValue()); + } + + public void testGeoHashPrecisionAsInteger() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true) + .field("geohash_precision", 10).endObject().endObject().endObject().endObject().string(); + + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); + Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); + DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser() + .parse("type", new CompressedXContent(mapping)); + FieldMapper mapper = defaultMapper.mappers().smartNameFieldMapper("point"); + assertThat(mapper, instanceOf(BaseGeoPointFieldMapper.class)); + BaseGeoPointFieldMapper geoPointFieldMapper = (BaseGeoPointFieldMapper) mapper; + assertThat(((LegacyGeoPointFieldType)geoPointFieldMapper.fieldType()).geoHashPrecision(), is(10)); + } + + public void testGeoHashPrecisionAsLength() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("point").field("type", "geo_point").field("geohash", true) + .field("geohash_precision", "5m").endObject().endObject() + .endObject().endObject().string(); + + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); + Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); + DocumentMapper defaultMapper = createIndex("test", settings).mapperService().documentMapperParser() + .parse("type", new CompressedXContent(mapping)); + FieldMapper mapper = defaultMapper.mappers().smartNameFieldMapper("point"); + assertThat(mapper, instanceOf(BaseGeoPointFieldMapper.class)); + BaseGeoPointFieldMapper geoPointFieldMapper = (BaseGeoPointFieldMapper) mapper; + assertThat(((LegacyGeoPointFieldType)geoPointFieldMapper.fieldType()).geoHashPrecision(), is(10)); + } +} diff --git a/core/src/test/java/org/elasticsearch/index/mapper/MultiFieldsIntegrationIT.java b/core/src/test/java/org/elasticsearch/index/mapper/MultiFieldsIntegrationIT.java index e11f0b90e8..8711ead6ed 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/MultiFieldsIntegrationIT.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/MultiFieldsIntegrationIT.java @@ -128,7 +128,7 @@ public class MultiFieldsIntegrationIT extends ESIntegTestCase { .setQuery(constantScoreQuery(geoDistanceQuery("a").point(51, 19).distance(50, DistanceUnit.KILOMETERS))) .get(); assertThat(countResponse.getHits().totalHits(), equalTo(1L)); - countResponse = client().prepareSearch("my-index").setSize(0).setQuery(matchQuery("a.b", point.toString())).get(); + countResponse = client().prepareSearch("my-index").setSize(0).setQuery(matchQuery("a.b", point.geohash())).get(); assertThat(countResponse.getHits().totalHits(), equalTo(1L)); } diff --git a/core/src/test/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilderTests.java index ea020b5f48..9c9a80e63c 100644 --- a/core/src/test/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilderTests.java @@ -266,8 +266,10 @@ public class GeoBoundingBoxQueryBuilderTests extends AbstractQueryTestCase<GeoBo } else { assertTrue("Found no indexed geo query.", query instanceof LegacyInMemoryGeoBoundingBoxQuery); } - } else { + } else if (context.indexVersionCreated().before(Version.V_5_0_0_alpha6)) { assertTrue("Found no indexed geo query.", query instanceof GeoPointInBBoxQuery); + } else { + assertTrue("Found no indexed geo query.", query instanceof Query); } } } @@ -429,7 +431,7 @@ public class GeoBoundingBoxQueryBuilderTests extends AbstractQueryTestCase<GeoBo assertThat(filter.topLeft().lon(), closeTo(-70, 1E-5)); assertThat(filter.bottomRight().lat(), closeTo(30, 1E-5)); assertThat(filter.bottomRight().lon(), closeTo(-80, 1E-5)); - } else { + } else if (shardContext.indexVersionCreated().before(Version.V_5_0_0_alpha6)) { GeoPointInBBoxQuery q = (GeoPointInBBoxQuery) parsedQuery; assertThat(q.getField(), equalTo(GEO_POINT_FIELD_NAME)); assertThat(q.getMaxLat(), closeTo(40, 1E-5)); diff --git a/core/src/test/java/org/elasticsearch/index/query/GeoDistanceQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/GeoDistanceQueryBuilderTests.java index 676041fdd8..4d94834b3b 100644 --- a/core/src/test/java/org/elasticsearch/index/query/GeoDistanceQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/GeoDistanceQueryBuilderTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.index.query; +import org.apache.lucene.document.LatLonPoint; import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.spatial.geopoint.search.GeoPointDistanceQuery; @@ -155,18 +156,21 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista } private void assertGeoPointQuery(GeoDistanceQueryBuilder queryBuilder, Query query) throws IOException { - assertThat(query, instanceOf(GeoPointDistanceQuery.class)); - GeoPointDistanceQuery geoQuery = (GeoPointDistanceQuery) query; - assertThat(geoQuery.getField(), equalTo(queryBuilder.fieldName())); - if (queryBuilder.point() != null) { - assertThat(geoQuery.getCenterLat(), equalTo(queryBuilder.point().lat())); - assertThat(geoQuery.getCenterLon(), equalTo(queryBuilder.point().lon())); - } - double distance = queryBuilder.distance(); - if (queryBuilder.geoDistance() != null) { - distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT); - distance = org.elasticsearch.common.geo.GeoUtils.maxRadialDistance(queryBuilder.point(), distance); - assertThat(geoQuery.getRadiusMeters(), closeTo(distance, GeoUtils.TOLERANCE)); + Version version = createShardContext().indexVersionCreated(); + if (version.before(Version.V_5_0_0_alpha6)) { + assertThat(query, instanceOf(GeoPointDistanceQuery.class)); + GeoPointDistanceQuery geoQuery = (GeoPointDistanceQuery) query; + assertThat(geoQuery.getField(), equalTo(queryBuilder.fieldName())); + if (queryBuilder.point() != null) { + assertThat(geoQuery.getCenterLat(), equalTo(queryBuilder.point().lat())); + assertThat(geoQuery.getCenterLon(), equalTo(queryBuilder.point().lon())); + } + double distance = queryBuilder.distance(); + if (queryBuilder.geoDistance() != null) { + distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT); + distance = org.elasticsearch.common.geo.GeoUtils.maxRadialDistance(queryBuilder.point(), distance); + assertThat(geoQuery.getRadiusMeters(), closeTo(distance, GeoUtils.TOLERANCE)); + } } } @@ -345,7 +349,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista assertThat(q.lon(), closeTo(lon, 1E-5D)); assertThat(q.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY)); assertThat(q.maxInclusiveDistance(), closeTo(distanceUnit.convert(distance, DistanceUnit.MILES), 1E-5D)); - } else { + } else if (version.before(Version.V_5_0_0_alpha6)) { GeoPointDistanceQuery q = (GeoPointDistanceQuery) parsedQuery; assertThat(q.getField(), equalTo(GEO_POINT_FIELD_NAME)); assertThat(q.getCenterLat(), closeTo(lat, 1E-5D)); diff --git a/core/src/test/java/org/elasticsearch/index/query/GeoDistanceRangeQueryTests.java b/core/src/test/java/org/elasticsearch/index/query/GeoDistanceRangeQueryTests.java index 7b165d8a37..46433f57e2 100644 --- a/core/src/test/java/org/elasticsearch/index/query/GeoDistanceRangeQueryTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/GeoDistanceRangeQueryTests.java @@ -204,7 +204,9 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc @Override public void testToQuery() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); - super.testToQuery(); + if (createShardContext().indexVersionCreated().before(Version.V_5_0_0_alpha6)) { + super.testToQuery(); + } } public void testNullFieldName() { @@ -254,6 +256,11 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc } public void testNestedRangeQuery() throws IOException { + // geo distance range queries are no longer supported in 5.0 they are replaced by using aggregations or sort + if (createShardContext().indexVersionCreated().onOrAfter(Version.V_5_0_0_alpha6)) { + return; + } + // create a nested geo_point type with a subfield named "geohash" (explicit testing for ISSUE #15179) MapperService mapperService = createShardContext().getMapperService(); String nestedMapping = @@ -367,7 +374,9 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc @Override public void testMustRewrite() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); - super.testMustRewrite(); + if (createShardContext().indexVersionCreated().before(Version.V_5_0_0_alpha6)) { + super.testMustRewrite(); + } } public void testIgnoreUnmapped() throws IOException { diff --git a/core/src/test/java/org/elasticsearch/index/query/GeohashCellQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/GeohashCellQueryBuilderTests.java index e9e4a71190..ab0061af7e 100644 --- a/core/src/test/java/org/elasticsearch/index/query/GeohashCellQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/GeohashCellQueryBuilderTests.java @@ -24,6 +24,7 @@ import org.apache.lucene.queries.TermsQuery; import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; +import org.elasticsearch.Version; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.index.mapper.BaseGeoPointFieldMapper; @@ -87,7 +88,10 @@ public class GeohashCellQueryBuilderTests extends AbstractQueryTestCase<Builder> @Override public void testToQuery() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); - super.testToQuery(); + Version version = createShardContext().indexVersionCreated(); + if (version.before(Version.V_5_0_0_alpha6)) { + super.testToQuery(); + } } public void testNullField() { @@ -140,7 +144,10 @@ public class GeohashCellQueryBuilderTests extends AbstractQueryTestCase<Builder> @Override public void testMustRewrite() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); - super.testMustRewrite(); + Version version = createShardContext().indexVersionCreated(); + if (version.before(Version.V_5_0_0_alpha6)) { + super.testMustRewrite(); + } } public void testIgnoreUnmapped() throws IOException { diff --git a/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java index f122d66ebe..ccb76b9c85 100644 --- a/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java @@ -25,6 +25,7 @@ import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.join.ScoreMode; import org.apache.lucene.search.join.ToParentBlockJoinQuery; +import org.elasticsearch.Version; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.index.mapper.MapperService; @@ -49,6 +50,8 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu @Override protected void initializeAdditionalMappings(MapperService mapperService) throws IOException { + String geoFieldMapping = (mapperService.getIndexSettings().getIndexVersionCreated().before(Version.V_5_0_0_alpha6)) ? + LEGACY_GEO_POINT_FIELD_MAPPING : "type=geo_point"; mapperService.merge("nested_doc", new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef("nested_doc", STRING_FIELD_NAME, "type=text", INT_FIELD_NAME, "type=integer", @@ -56,7 +59,7 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu BOOLEAN_FIELD_NAME, "type=boolean", DATE_FIELD_NAME, "type=date", OBJECT_FIELD_NAME, "type=object", - GEO_POINT_FIELD_NAME, GEO_POINT_FIELD_MAPPING, + GEO_POINT_FIELD_NAME, geoFieldMapping, "nested1", "type=nested" ).string()), MapperService.MergeReason.MAPPING_UPDATE, false); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AbstractGeoTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AbstractGeoTestCase.java index 5cc6ec5863..7cca4baade 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AbstractGeoTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/AbstractGeoTestCase.java @@ -74,7 +74,7 @@ public abstract class AbstractGeoTestCase extends ESIntegTestCase { public void setupSuiteScopeCluster() throws Exception { createIndex(UNMAPPED_IDX_NAME); assertAcked(prepareCreate(IDX_NAME) - .addMapping("type", SINGLE_VALUED_FIELD_NAME, "type=geo_point,geohash_prefix=true,geohash_precision=12", + .addMapping("type", SINGLE_VALUED_FIELD_NAME, "type=geo_point", MULTI_VALUED_FIELD_NAME, "type=geo_point", NUMBER_FIELD_NAME, "type=long", "tag", "type=keyword")); singleTopLeft = new GeoPoint(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); diff --git a/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java b/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java index f9f59ac8b3..19904be38b 100644 --- a/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java +++ b/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java @@ -2728,7 +2728,6 @@ public class HighlighterSearchIT extends ESIntegTestCase { .startObject("properties") .startObject("geo_point") .field("type", "geo_point") - .field("geohash", true) .endObject() .startObject("text") .field("type", "text") diff --git a/core/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java b/core/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java index e6d7700c84..481d01f4fe 100644 --- a/core/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java +++ b/core/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java @@ -446,7 +446,7 @@ public class GeoFilterIT extends ESIntegTestCase { } } - public void testGeohashCellFilter() throws IOException { + public void testLegacyGeohashCellFilter() throws IOException { String geohash = randomhash(10); logger.info("Testing geohash_cell filter for [{}]", geohash); @@ -457,8 +457,11 @@ public class GeoFilterIT extends ESIntegTestCase { logger.info("Parent Neighbors {}", parentNeighbors); ensureYellow(); + Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); + Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); - client().admin().indices().prepareCreate("locations").addMapping("location", "pin", "type=geo_point,geohash_prefix=true,lat_lon=false").execute().actionGet(); + client().admin().indices().prepareCreate("locations").setSettings(settings).addMapping("location", "pin", + "type=geo_point,geohash_prefix=true,lat_lon=false").execute().actionGet(); // Index a pin client().prepareIndex("locations", "location", "1").setCreate(true).setSource("pin", geohash).execute().actionGet(); diff --git a/core/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java b/core/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java index 9fae823c43..0901a6201a 100644 --- a/core/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java +++ b/core/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java @@ -21,8 +21,10 @@ package org.elasticsearch.search.suggest; import com.carrotsearch.randomizedtesting.generators.RandomStrings; import org.apache.lucene.util.LuceneTestCase.SuppressCodecs; +import org.elasticsearch.Version; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.geo.GeoHashUtils; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.settings.Settings; @@ -38,6 +40,7 @@ import org.elasticsearch.search.suggest.completion.context.ContextMapping; import org.elasticsearch.search.suggest.completion.context.GeoContextMapping; import org.elasticsearch.search.suggest.completion.context.GeoQueryContext; import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.VersionUtils; import java.io.IOException; import java.util.ArrayList; @@ -557,7 +560,8 @@ public class ContextCompletionSuggestSearchIT extends ESIntegTestCase { } public void testGeoField() throws Exception { - +// Version version = VersionUtils.randomVersionBetween(random(), Version.V_2_0_0, Version.V_5_0_0_alpha5); +// Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, version).build(); XContentBuilder mapping = jsonBuilder(); mapping.startObject(); mapping.startObject(TYPE); diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java index 0560ec2a91..08aba9f3e7 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java @@ -143,7 +143,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>> protected static final String DATE_FIELD_NAME = "mapped_date"; protected static final String OBJECT_FIELD_NAME = "mapped_object"; protected static final String GEO_POINT_FIELD_NAME = "mapped_geo_point"; - protected static final String GEO_POINT_FIELD_MAPPING = "type=geo_point,lat_lon=true,geohash=true,geohash_prefix=true"; + protected static final String LEGACY_GEO_POINT_FIELD_MAPPING = "type=geo_point,lat_lon=true,geohash=true,geohash_prefix=true"; protected static final String GEO_SHAPE_FIELD_NAME = "mapped_geo_shape"; protected static final String[] MAPPED_FIELD_NAMES = new String[]{STRING_FIELD_NAME, INT_FIELD_NAME, DOUBLE_FIELD_NAME, BOOLEAN_FIELD_NAME, DATE_FIELD_NAME, OBJECT_FIELD_NAME, GEO_POINT_FIELD_NAME, GEO_SHAPE_FIELD_NAME}; @@ -1100,6 +1100,9 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>> }); indicesQueriesRegistry = injector.getInstance(IndicesQueriesRegistry.class); + String geoFieldMapping = (idxSettings.getIndexVersionCreated().before(Version.V_5_0_0_alpha6)) ? + LEGACY_GEO_POINT_FIELD_MAPPING : "type=geo_point"; + for (String type : currentTypes) { mapperService.merge(type, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(type, STRING_FIELD_NAME, "type=text", @@ -1109,7 +1112,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>> BOOLEAN_FIELD_NAME, "type=boolean", DATE_FIELD_NAME, "type=date", OBJECT_FIELD_NAME, "type=object", - GEO_POINT_FIELD_NAME, GEO_POINT_FIELD_MAPPING, + GEO_POINT_FIELD_NAME, geoFieldMapping, GEO_SHAPE_FIELD_NAME, "type=geo_shape" ).string()), MapperService.MergeReason.MAPPING_UPDATE, false); // also add mappings for two inner field in the object field |