[Backport] Refactor Spatial Field Mappers (#55696)
This commit refactors all spatial Field Mappers to a common AbstractGeometryFieldMapper that implements shared parameter functionality (e.g., ignore_malformed, ignore_z_value) and provides a common framework for overriding type parsing, and building in xpack. Common shape functionality is implemented in a new AbstractShapeGeometryFieldMapper that is reused and overridden in GeoShapeFieldMapper, GeoShapeFieldMapperWithDocValues, LegacyGeoShapeFieldMapper, and ShapeFieldMapper. This abstraction provides a reusable foundation for adding new xpack features; such as coordinate reference system support.
This commit is contained in:
parent
e4ebe55d04
commit
b0e8a8a4d1
|
@ -29,7 +29,7 @@ import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
|||
import org.elasticsearch.common.unit.DistanceUnit;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentSubParser;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -42,7 +42,7 @@ import java.util.List;
|
|||
* complies with geojson specification: https://tools.ietf.org/html/rfc7946
|
||||
*/
|
||||
abstract class GeoJsonParser {
|
||||
protected static ShapeBuilder parse(XContentParser parser, AbstractGeometryFieldMapper shapeMapper)
|
||||
protected static ShapeBuilder parse(XContentParser parser, AbstractShapeGeometryFieldMapper shapeMapper)
|
||||
throws IOException {
|
||||
GeoShapeType shapeType = null;
|
||||
DistanceUnit.Distance radius = null;
|
||||
|
@ -50,13 +50,13 @@ abstract class GeoJsonParser {
|
|||
GeometryCollectionBuilder geometryCollections = null;
|
||||
|
||||
Orientation orientation = (shapeMapper == null)
|
||||
? AbstractGeometryFieldMapper.Defaults.ORIENTATION.value()
|
||||
? AbstractShapeGeometryFieldMapper.Defaults.ORIENTATION.value()
|
||||
: shapeMapper.orientation();
|
||||
Explicit<Boolean> coerce = (shapeMapper == null)
|
||||
? AbstractGeometryFieldMapper.Defaults.COERCE
|
||||
? AbstractShapeGeometryFieldMapper.Defaults.COERCE
|
||||
: shapeMapper.coerce();
|
||||
Explicit<Boolean> ignoreZValue = (shapeMapper == null)
|
||||
? AbstractGeometryFieldMapper.Defaults.IGNORE_Z_VALUE
|
||||
? AbstractShapeGeometryFieldMapper.Defaults.IGNORE_Z_VALUE
|
||||
: shapeMapper.ignoreZValue();
|
||||
|
||||
String malformedException = null;
|
||||
|
@ -208,7 +208,7 @@ abstract class GeoJsonParser {
|
|||
* @return Geometry[] geometries of the GeometryCollection
|
||||
* @throws IOException Thrown if an error occurs while reading from the XContentParser
|
||||
*/
|
||||
static GeometryCollectionBuilder parseGeometries(XContentParser parser, AbstractGeometryFieldMapper mapper) throws
|
||||
static GeometryCollectionBuilder parseGeometries(XContentParser parser, AbstractShapeGeometryFieldMapper mapper) throws
|
||||
IOException {
|
||||
if (parser.currentToken() != XContentParser.Token.START_ARRAY) {
|
||||
throw new ElasticsearchParseException("geometries must be an array of geojson objects");
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.elasticsearch.common.geo.builders.PolygonBuilder;
|
|||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -63,7 +63,7 @@ public class GeoWKTParser {
|
|||
// no instance
|
||||
private GeoWKTParser() {}
|
||||
|
||||
public static ShapeBuilder parse(XContentParser parser, final AbstractGeometryFieldMapper shapeMapper)
|
||||
public static ShapeBuilder parse(XContentParser parser, final AbstractShapeGeometryFieldMapper shapeMapper)
|
||||
throws IOException, ElasticsearchParseException {
|
||||
return parseExpectedType(parser, null, shapeMapper);
|
||||
}
|
||||
|
@ -75,12 +75,12 @@ public class GeoWKTParser {
|
|||
|
||||
/** throws an exception if the parsed geometry type does not match the expected shape type */
|
||||
public static ShapeBuilder parseExpectedType(XContentParser parser, final GeoShapeType shapeType,
|
||||
final AbstractGeometryFieldMapper shapeMapper)
|
||||
final AbstractShapeGeometryFieldMapper shapeMapper)
|
||||
throws IOException, ElasticsearchParseException {
|
||||
try (StringReader reader = new StringReader(parser.text())) {
|
||||
Explicit<Boolean> ignoreZValue = (shapeMapper == null) ? AbstractGeometryFieldMapper.Defaults.IGNORE_Z_VALUE :
|
||||
Explicit<Boolean> ignoreZValue = (shapeMapper == null) ? AbstractShapeGeometryFieldMapper.Defaults.IGNORE_Z_VALUE :
|
||||
shapeMapper.ignoreZValue();
|
||||
Explicit<Boolean> coerce = (shapeMapper == null) ? AbstractGeometryFieldMapper.Defaults.COERCE : shapeMapper.coerce();
|
||||
Explicit<Boolean> coerce = (shapeMapper == null) ? AbstractShapeGeometryFieldMapper.Defaults.COERCE : shapeMapper.coerce();
|
||||
// setup the tokenizer; configured to read words w/o numbers
|
||||
StreamTokenizer tokenizer = new StreamTokenizer(reader);
|
||||
tokenizer.resetSyntax();
|
||||
|
@ -258,7 +258,7 @@ public class GeoWKTParser {
|
|||
return null;
|
||||
}
|
||||
PolygonBuilder builder = new PolygonBuilder(parseLinearRing(stream, ignoreZValue, coerce),
|
||||
AbstractGeometryFieldMapper.Defaults.ORIENTATION.value());
|
||||
AbstractShapeGeometryFieldMapper.Defaults.ORIENTATION.value());
|
||||
while (nextCloserOrComma(stream).equals(COMMA)) {
|
||||
builder.hole(parseLinearRing(stream, ignoreZValue, coerce));
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
|||
import org.elasticsearch.common.xcontent.XContent;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.MapXContentParser;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
@ -50,7 +50,7 @@ public interface ShapeParser {
|
|||
* if the parsers current token has been <code>null</code>
|
||||
* @throws IOException if the input could not be read
|
||||
*/
|
||||
static ShapeBuilder parse(XContentParser parser, AbstractGeometryFieldMapper shapeMapper) throws IOException {
|
||||
static ShapeBuilder parse(XContentParser parser, AbstractShapeGeometryFieldMapper shapeMapper) throws IOException {
|
||||
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
|
||||
return null;
|
||||
} if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
|
||||
|
|
|
@ -23,122 +23,53 @@ import org.apache.lucene.index.IndexableField;
|
|||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.common.geo.SpatialStrategy;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper.DeprecatedParameters;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.elasticsearch.index.mapper.GeoPointFieldMapper.Names.IGNORE_MALFORMED;
|
||||
|
||||
/**
|
||||
* Base class for {@link GeoShapeFieldMapper} and {@link LegacyGeoShapeFieldMapper}
|
||||
* Base field mapper class for all spatial field types
|
||||
*/
|
||||
public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends FieldMapper {
|
||||
|
||||
public abstract class AbstractGeometryFieldMapper extends FieldMapper {
|
||||
|
||||
public static class Names {
|
||||
public static final ParseField ORIENTATION = new ParseField("orientation");
|
||||
public static final ParseField COERCE = new ParseField("coerce");
|
||||
public static final ParseField IGNORE_MALFORMED = new ParseField("ignore_malformed");
|
||||
public static final ParseField IGNORE_Z_VALUE = new ParseField("ignore_z_value");
|
||||
}
|
||||
|
||||
public static class Defaults {
|
||||
public static final Explicit<Orientation> ORIENTATION = new Explicit<>(Orientation.RIGHT, false);
|
||||
public static final Explicit<Boolean> COERCE = new Explicit<>(false, false);
|
||||
public static final Explicit<Boolean> IGNORE_MALFORMED = new Explicit<>(false, false);
|
||||
public static final Explicit<Boolean> IGNORE_Z_VALUE = new Explicit<>(true, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Interface representing an preprocessor in geo-shape indexing pipeline
|
||||
*/
|
||||
public interface Indexer<Parsed, Processed> {
|
||||
|
||||
Processed prepareForIndexing(Parsed geometry);
|
||||
|
||||
Class<Processed> processedClass();
|
||||
|
||||
List<IndexableField> indexShape(ParseContext context, Processed shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* interface representing parser in geo shape indexing pipeline
|
||||
*/
|
||||
public interface Parser<Parsed> {
|
||||
|
||||
Parsed parse(XContentParser parser, AbstractGeometryFieldMapper mapper) throws IOException, ParseException;
|
||||
|
||||
}
|
||||
|
||||
public abstract static class Builder<T extends Builder, Y extends AbstractGeometryFieldMapper>
|
||||
extends FieldMapper.Builder<T, Y> {
|
||||
protected Boolean coerce;
|
||||
protected Boolean ignoreMalformed;
|
||||
protected Boolean ignoreZValue;
|
||||
protected Orientation orientation;
|
||||
|
||||
/** default builder - used for external mapper*/
|
||||
public Builder(String name, MappedFieldType fieldType, MappedFieldType defaultFieldType) {
|
||||
super(name, fieldType, defaultFieldType);
|
||||
}
|
||||
|
||||
public Builder(String name, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
boolean coerce, boolean ignoreMalformed, Orientation orientation, boolean ignoreZ) {
|
||||
public Builder(String name, MappedFieldType fieldType, MappedFieldType defaultFieldType, boolean ignoreMalformed,
|
||||
boolean ignoreZValue) {
|
||||
super(name, fieldType, defaultFieldType);
|
||||
this.coerce = coerce;
|
||||
this.ignoreMalformed = ignoreMalformed;
|
||||
this.orientation = orientation;
|
||||
this.ignoreZValue = ignoreZ;
|
||||
}
|
||||
|
||||
public Builder coerce(boolean coerce) {
|
||||
this.coerce = coerce;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> coerce(BuilderContext context) {
|
||||
if (coerce != null) {
|
||||
return new Explicit<>(coerce, true);
|
||||
}
|
||||
if (context.indexSettings() != null) {
|
||||
return new Explicit<>(COERCE_SETTING.get(context.indexSettings()), false);
|
||||
}
|
||||
return Defaults.COERCE;
|
||||
}
|
||||
|
||||
public Builder orientation(Orientation orientation) {
|
||||
this.orientation = orientation;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Explicit<Orientation> orientation() {
|
||||
if (orientation != null) {
|
||||
return new Explicit<>(orientation, true);
|
||||
}
|
||||
return Defaults.ORIENTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean defaultDocValues(Version indexCreated) {
|
||||
return false;
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
}
|
||||
|
||||
public Builder ignoreMalformed(boolean ignoreMalformed) {
|
||||
|
@ -156,13 +87,27 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
return Defaults.IGNORE_MALFORMED;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreZValue() {
|
||||
public Explicit<Boolean> ignoreMalformed() {
|
||||
if (ignoreMalformed != null) {
|
||||
return new Explicit<>(ignoreMalformed, true);
|
||||
}
|
||||
return AbstractShapeGeometryFieldMapper.Defaults.IGNORE_MALFORMED;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreZValue(BuilderContext context) {
|
||||
if (ignoreZValue != null) {
|
||||
return new Explicit<>(ignoreZValue, true);
|
||||
}
|
||||
return Defaults.IGNORE_Z_VALUE;
|
||||
}
|
||||
|
||||
public Explicit<Boolean> ignoreZValue() {
|
||||
if (ignoreZValue != null) {
|
||||
return new Explicit<>(ignoreZValue, true);
|
||||
}
|
||||
return AbstractShapeGeometryFieldMapper.Defaults.IGNORE_Z_VALUE;
|
||||
}
|
||||
|
||||
public Builder ignoreZValue(final boolean ignoreZValue) {
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
return this;
|
||||
|
@ -177,88 +122,52 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
if (name().isEmpty()) {
|
||||
throw new IllegalArgumentException("name cannot be empty string");
|
||||
}
|
||||
|
||||
AbstractGeometryFieldType ft = (AbstractGeometryFieldType)fieldType();
|
||||
ft.setOrientation(orientation().value());
|
||||
}
|
||||
}
|
||||
|
||||
protected static final String DEPRECATED_PARAMETERS_KEY = "deprecated_parameters";
|
||||
public abstract static class TypeParser<T extends Builder> implements Mapper.TypeParser {
|
||||
protected abstract T newBuilder(String name, Map<String, Object> params);
|
||||
|
||||
public abstract static class TypeParser implements Mapper.TypeParser {
|
||||
protected abstract Builder newBuilder(String name, Map<String, Object> params);
|
||||
|
||||
protected boolean parseXContentParameters(String name, Map.Entry<String, Object> entry, Map<String, Object> params)
|
||||
throws MapperParsingException {
|
||||
if (DeprecatedParameters.parse(name, entry.getKey(), entry.getValue(),
|
||||
(DeprecatedParameters)params.get(DEPRECATED_PARAMETERS_KEY))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
boolean parsedDeprecatedParameters = false;
|
||||
params.put(DEPRECATED_PARAMETERS_KEY, new DeprecatedParameters());
|
||||
public T parse(String name, Map<String, Object> node, Map<String, Object> params, ParserContext parserContext) {
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<String, Object> entry = iterator.next();
|
||||
String fieldName = entry.getKey();
|
||||
Object fieldNode = entry.getValue();
|
||||
if (parseXContentParameters(name, entry, params)) {
|
||||
parsedDeprecatedParameters = true;
|
||||
iterator.remove();
|
||||
} else if (Names.ORIENTATION.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
params.put(Names.ORIENTATION.getPreferredName(), ShapeBuilder.Orientation.fromString(fieldNode.toString()));
|
||||
iterator.remove();
|
||||
} else if (IGNORE_MALFORMED.equals(fieldName)) {
|
||||
params.put(IGNORE_MALFORMED, XContentMapValues.nodeBooleanValue(fieldNode, name + ".ignore_malformed"));
|
||||
iterator.remove();
|
||||
} else if (Names.COERCE.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
params.put(Names.COERCE.getPreferredName(),
|
||||
XContentMapValues.nodeBooleanValue(fieldNode, name + "." + Names.COERCE.getPreferredName()));
|
||||
iterator.remove();
|
||||
} else if (GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName().equals(fieldName)) {
|
||||
params.put(GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName(),
|
||||
XContentMapValues.nodeBooleanValue(fieldNode,
|
||||
name + "." + GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName()));
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (parserContext.indexVersionCreated().onOrAfter(Version.V_6_6_0) && parsedDeprecatedParameters == false) {
|
||||
params.remove(DEPRECATED_PARAMETERS_KEY);
|
||||
}
|
||||
Builder builder = newBuilder(name, params);
|
||||
String propName = entry.getKey();
|
||||
Object propNode = entry.getValue();
|
||||
|
||||
if (params.containsKey(Names.COERCE.getPreferredName())) {
|
||||
builder.coerce((Boolean)params.get(Names.COERCE.getPreferredName()));
|
||||
if (Names.IGNORE_MALFORMED.match(propName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
params.put(Names.IGNORE_MALFORMED.getPreferredName(), XContentMapValues.nodeBooleanValue(propNode,
|
||||
name + ".ignore_malformed"));
|
||||
iterator.remove();
|
||||
} else if (Names.IGNORE_Z_VALUE.getPreferredName().equals(propName)) {
|
||||
params.put(GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName(),
|
||||
XContentMapValues.nodeBooleanValue(propNode, name + "." + Names.IGNORE_Z_VALUE.getPreferredName()));
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
T builder = newBuilder(name, params);
|
||||
|
||||
if (params.containsKey(GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName())) {
|
||||
builder.ignoreZValue((Boolean)params.get(GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName()));
|
||||
}
|
||||
|
||||
if (params.containsKey(IGNORE_MALFORMED)) {
|
||||
builder.ignoreMalformed((Boolean)params.get(IGNORE_MALFORMED));
|
||||
if (params.containsKey(Names.IGNORE_MALFORMED.getPreferredName())) {
|
||||
builder.ignoreMalformed((Boolean)params.get(Names.IGNORE_MALFORMED.getPreferredName()));
|
||||
}
|
||||
|
||||
if (params.containsKey(Names.ORIENTATION.getPreferredName())) {
|
||||
builder.orientation((Orientation)params.get(Names.ORIENTATION.getPreferredName()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public T parse(String name, Map<String, Object> node, ParserContext parserContext)
|
||||
throws MapperParsingException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
return parse(name, node, params, parserContext);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class AbstractGeometryFieldType<Parsed, Processed> extends AbstractSearchableGeometryFieldType {
|
||||
protected Orientation orientation = Defaults.ORIENTATION.value();
|
||||
|
||||
protected Indexer<Parsed, Processed> geometryIndexer;
|
||||
|
||||
protected Parser<Parsed> geometryParser;
|
||||
|
||||
|
||||
public abstract static class AbstractGeometryFieldType extends MappedFieldType {
|
||||
protected QueryProcessor geometryQueryBuilder;
|
||||
|
||||
protected AbstractGeometryFieldType() {
|
||||
setIndexOptions(IndexOptions.DOCS);
|
||||
|
@ -270,26 +179,27 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
|
||||
protected AbstractGeometryFieldType(AbstractGeometryFieldType ref) {
|
||||
super(ref);
|
||||
this.orientation = ref.orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!super.equals(o)) return false;
|
||||
AbstractGeometryFieldType that = (AbstractGeometryFieldType) o;
|
||||
return orientation == that.orientation;
|
||||
public void setGeometryQueryBuilder(QueryProcessor geometryQueryBuilder) {
|
||||
this.geometryQueryBuilder = geometryQueryBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), orientation);
|
||||
public QueryProcessor geometryQueryBuilder() {
|
||||
return geometryQueryBuilder;
|
||||
}
|
||||
|
||||
public Orientation orientation() { return this.orientation; }
|
||||
/**
|
||||
* interface representing a query builder that generates a query from the given geometry
|
||||
*/
|
||||
public interface QueryProcessor {
|
||||
Query process(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context);
|
||||
|
||||
public void setOrientation(Orientation orientation) {
|
||||
checkIfFrozen();
|
||||
this.orientation = orientation;
|
||||
@Deprecated
|
||||
default Query process(Geometry shape, String fieldName, SpatialStrategy strategy, ShapeRelation relation,
|
||||
QueryShardContext context) {
|
||||
return process(shape, fieldName, relation, context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -300,36 +210,18 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
@Override
|
||||
public Query termQuery(Object value, QueryShardContext context) {
|
||||
throw new QueryShardException(context,
|
||||
"Geometry fields do not support exact searching, use dedicated geometry queries instead");
|
||||
}
|
||||
|
||||
public void setGeometryIndexer(Indexer<Parsed, Processed> geometryIndexer) {
|
||||
this.geometryIndexer = geometryIndexer;
|
||||
}
|
||||
|
||||
protected Indexer<Parsed, Processed> geometryIndexer() {
|
||||
return geometryIndexer;
|
||||
}
|
||||
|
||||
public void setGeometryParser(Parser<Parsed> geometryParser) {
|
||||
this.geometryParser = geometryParser;
|
||||
}
|
||||
|
||||
protected Parser<Parsed> geometryParser() {
|
||||
return geometryParser;
|
||||
"Geometry fields do not support exact searching, use dedicated geometry queries instead: ["
|
||||
+ name() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> coerce;
|
||||
protected Explicit<Boolean> ignoreMalformed;
|
||||
protected Explicit<Boolean> ignoreZValue;
|
||||
|
||||
protected AbstractGeometryFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce,
|
||||
Explicit<Boolean> ignoreZValue, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
Settings indexSettings, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> ignoreZValue, MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo);
|
||||
this.coerce = coerce;
|
||||
this.ignoreMalformed = ignoreMalformed;
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
}
|
||||
|
@ -338,9 +230,7 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
protected void doMerge(Mapper mergeWith) {
|
||||
super.doMerge(mergeWith);
|
||||
AbstractGeometryFieldMapper gsfm = (AbstractGeometryFieldMapper)mergeWith;
|
||||
if (gsfm.coerce.explicit()) {
|
||||
this.coerce = gsfm.coerce;
|
||||
}
|
||||
|
||||
if (gsfm.ignoreMalformed.explicit()) {
|
||||
this.ignoreMalformed = gsfm.ignoreMalformed;
|
||||
}
|
||||
|
@ -356,26 +246,15 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
|
||||
@Override
|
||||
public void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
builder.field("type", contentType());
|
||||
AbstractGeometryFieldType ft = (AbstractGeometryFieldType)fieldType();
|
||||
if (includeDefaults || ft.orientation() != Defaults.ORIENTATION.value()) {
|
||||
builder.field(Names.ORIENTATION.getPreferredName(), ft.orientation());
|
||||
}
|
||||
if (includeDefaults || coerce.explicit()) {
|
||||
builder.field(Names.COERCE.getPreferredName(), coerce.value());
|
||||
}
|
||||
super.doXContentBody(builder, includeDefaults, params);
|
||||
if (includeDefaults || ignoreMalformed.explicit()) {
|
||||
builder.field(IGNORE_MALFORMED, ignoreMalformed.value());
|
||||
builder.field(Names.IGNORE_MALFORMED.getPreferredName(), ignoreMalformed.value());
|
||||
}
|
||||
if (includeDefaults || ignoreZValue.explicit()) {
|
||||
builder.field(GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName(), ignoreZValue.value());
|
||||
builder.field(Names.IGNORE_Z_VALUE.getPreferredName(), ignoreZValue.value());
|
||||
}
|
||||
}
|
||||
|
||||
public Explicit<Boolean> coerce() {
|
||||
return coerce;
|
||||
}
|
||||
|
||||
public Explicit<Boolean> ignoreMalformed() {
|
||||
return ignoreMalformed;
|
||||
}
|
||||
|
@ -383,41 +262,4 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
|
|||
public Explicit<Boolean> ignoreZValue() {
|
||||
return ignoreZValue;
|
||||
}
|
||||
|
||||
public Orientation orientation() {
|
||||
return ((AbstractGeometryFieldType)fieldType).orientation();
|
||||
}
|
||||
|
||||
/** parsing logic for geometry indexing */
|
||||
@Override
|
||||
public void parse(ParseContext context) throws IOException {
|
||||
AbstractGeometryFieldType fieldType = (AbstractGeometryFieldType)fieldType();
|
||||
|
||||
@SuppressWarnings("unchecked") Indexer<Parsed, Processed> geometryIndexer = fieldType.geometryIndexer();
|
||||
@SuppressWarnings("unchecked") Parser<Parsed> geometryParser = fieldType.geometryParser();
|
||||
try {
|
||||
Processed shape = context.parseExternalValue(geometryIndexer.processedClass());
|
||||
if (shape == null) {
|
||||
Parsed geometry = geometryParser.parse(context.parser(), this);
|
||||
if (geometry == null) {
|
||||
return;
|
||||
}
|
||||
shape = geometryIndexer.prepareForIndexing(geometry);
|
||||
}
|
||||
|
||||
List<IndexableField> fields = new ArrayList<>();
|
||||
fields.addAll(geometryIndexer.indexShape(context, shape));
|
||||
createFieldNamesField(context, fields);
|
||||
for (IndexableField field : fields) {
|
||||
context.doc().add(field);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (ignoreMalformed.value() == false) {
|
||||
throw new MapperParsingException("failed to parse field [{}] of type [{}]", e, fieldType().name(),
|
||||
fieldType().typeName());
|
||||
}
|
||||
context.addIgnoredField(fieldType().name());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,63 +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.search.Query;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.common.geo.SpatialStrategy;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
|
||||
/**
|
||||
* a base class for geometry types that support shape query builder
|
||||
*/
|
||||
public abstract class AbstractSearchableGeometryFieldType extends MappedFieldType {
|
||||
|
||||
protected QueryProcessor geometryQueryBuilder;
|
||||
|
||||
protected AbstractSearchableGeometryFieldType() {
|
||||
}
|
||||
|
||||
protected AbstractSearchableGeometryFieldType(AbstractSearchableGeometryFieldType ref) {
|
||||
super(ref);
|
||||
}
|
||||
|
||||
public void setGeometryQueryBuilder(QueryProcessor geometryQueryBuilder) {
|
||||
this.geometryQueryBuilder = geometryQueryBuilder;
|
||||
}
|
||||
|
||||
public QueryProcessor geometryQueryBuilder() {
|
||||
return geometryQueryBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* interface representing a query builder that generates a query from the given shape
|
||||
*/
|
||||
public interface QueryProcessor {
|
||||
Query process(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context);
|
||||
|
||||
@Deprecated
|
||||
default Query process(Geometry shape, String fieldName, SpatialStrategy strategy, ShapeRelation relation,
|
||||
QueryShardContext context) {
|
||||
return process(shape, fieldName, relation, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* 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.index.IndexableField;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper.DeprecatedParameters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Base class for {@link GeoShapeFieldMapper} and {@link LegacyGeoShapeFieldMapper}
|
||||
*/
|
||||
public abstract class AbstractShapeGeometryFieldMapper<Parsed, Processed> extends AbstractGeometryFieldMapper {
|
||||
|
||||
public static class Names extends AbstractGeometryFieldMapper.Names {
|
||||
public static final ParseField ORIENTATION = new ParseField("orientation");
|
||||
public static final ParseField COERCE = new ParseField("coerce");
|
||||
}
|
||||
|
||||
public static class Defaults extends AbstractGeometryFieldMapper.Defaults {
|
||||
public static final Explicit<Orientation> ORIENTATION = new Explicit<>(Orientation.RIGHT, false);
|
||||
public static final Explicit<Boolean> COERCE = new Explicit<>(false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface representing an preprocessor in geo-shape indexing pipeline
|
||||
*/
|
||||
public interface Indexer<Parsed, Processed> {
|
||||
|
||||
Processed prepareForIndexing(Parsed geometry);
|
||||
|
||||
Class<Processed> processedClass();
|
||||
|
||||
List<IndexableField> indexShape(ParseContext context, Processed shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* interface representing parser in geo shape indexing pipeline
|
||||
*/
|
||||
public interface Parser<Parsed> {
|
||||
|
||||
Parsed parse(XContentParser parser, AbstractShapeGeometryFieldMapper mapper) throws IOException, ParseException;
|
||||
|
||||
}
|
||||
|
||||
public abstract static class Builder<T extends Builder, Y extends AbstractShapeGeometryFieldMapper>
|
||||
extends AbstractGeometryFieldMapper.Builder<T, Y> {
|
||||
protected Boolean coerce;
|
||||
protected Orientation orientation;
|
||||
|
||||
/** default builder - used for external mapper*/
|
||||
public Builder(String name, MappedFieldType fieldType, MappedFieldType defaultFieldType) {
|
||||
super(name, fieldType, defaultFieldType);
|
||||
}
|
||||
|
||||
public Builder(String name, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
boolean coerce, boolean ignoreMalformed, Orientation orientation, boolean ignoreZ) {
|
||||
super(name, fieldType, defaultFieldType, ignoreMalformed, ignoreZ);
|
||||
this.coerce = coerce;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
public Builder coerce(boolean coerce) {
|
||||
this.coerce = coerce;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> coerce(BuilderContext context) {
|
||||
if (coerce != null) {
|
||||
return new Explicit<>(coerce, true);
|
||||
}
|
||||
if (context.indexSettings() != null) {
|
||||
return new Explicit<>(COERCE_SETTING.get(context.indexSettings()), false);
|
||||
}
|
||||
return Defaults.COERCE;
|
||||
}
|
||||
|
||||
public Builder orientation(Orientation orientation) {
|
||||
this.orientation = orientation;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Explicit<Orientation> orientation() {
|
||||
if (orientation != null) {
|
||||
return new Explicit<>(orientation, true);
|
||||
}
|
||||
return Defaults.ORIENTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean defaultDocValues(Version indexCreated) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupFieldType(BuilderContext context) {
|
||||
super.setupFieldType(context);
|
||||
|
||||
AbstractShapeGeometryFieldType ft = (AbstractShapeGeometryFieldType)fieldType();
|
||||
ft.setOrientation(orientation().value());
|
||||
}
|
||||
}
|
||||
|
||||
protected static final String DEPRECATED_PARAMETERS_KEY = "deprecated_parameters";
|
||||
|
||||
public abstract static class TypeParser extends AbstractGeometryFieldMapper.TypeParser<Builder> {
|
||||
protected abstract Builder newBuilder(String name, Map<String, Object> params);
|
||||
|
||||
protected boolean parseXContentParameters(String name, Map.Entry<String, Object> entry, Map<String, Object> params)
|
||||
throws MapperParsingException {
|
||||
if (DeprecatedParameters.parse(name, entry.getKey(), entry.getValue(),
|
||||
(DeprecatedParameters)params.get(DEPRECATED_PARAMETERS_KEY))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder parse(String name, Map<String, Object> node, Map<String, Object> params, ParserContext parserContext) {
|
||||
boolean parsedDeprecatedParameters = false;
|
||||
params.put(DEPRECATED_PARAMETERS_KEY, new DeprecatedParameters());
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<String, Object> entry = iterator.next();
|
||||
String fieldName = entry.getKey();
|
||||
Object fieldNode = entry.getValue();
|
||||
if (parseXContentParameters(name, entry, params)) {
|
||||
parsedDeprecatedParameters = true;
|
||||
iterator.remove();
|
||||
} else if (Names.ORIENTATION.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
params.put(Names.ORIENTATION.getPreferredName(), ShapeBuilder.Orientation.fromString(fieldNode.toString()));
|
||||
iterator.remove();
|
||||
} else if (Names.COERCE.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
params.put(Names.COERCE.getPreferredName(),
|
||||
XContentMapValues.nodeBooleanValue(fieldNode, name + "." + Names.COERCE.getPreferredName()));
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (parserContext.indexVersionCreated().onOrAfter(Version.V_6_6_0) && parsedDeprecatedParameters == false) {
|
||||
params.remove(DEPRECATED_PARAMETERS_KEY);
|
||||
}
|
||||
|
||||
Builder builder = super.parse(name, node, params, parserContext);
|
||||
|
||||
if (params.containsKey(Names.COERCE.getPreferredName())) {
|
||||
builder.coerce((Boolean)params.get(Names.COERCE.getPreferredName()));
|
||||
}
|
||||
|
||||
if (params.containsKey(Names.ORIENTATION.getPreferredName())) {
|
||||
builder.orientation((Orientation)params.get(Names.ORIENTATION.getPreferredName()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class AbstractShapeGeometryFieldType<Parsed, Processed> extends AbstractGeometryFieldType {
|
||||
protected Orientation orientation = Defaults.ORIENTATION.value();
|
||||
|
||||
protected Indexer<Parsed, Processed> geometryIndexer;
|
||||
|
||||
protected Parser<Parsed> geometryParser;
|
||||
|
||||
protected AbstractShapeGeometryFieldType() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected AbstractShapeGeometryFieldType(AbstractShapeGeometryFieldType ref) {
|
||||
super(ref);
|
||||
this.orientation = ref.orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!super.equals(o)) return false;
|
||||
AbstractShapeGeometryFieldType that = (AbstractShapeGeometryFieldType) o;
|
||||
return orientation == that.orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), orientation);
|
||||
}
|
||||
|
||||
public Orientation orientation() { return this.orientation; }
|
||||
|
||||
public void setOrientation(Orientation orientation) {
|
||||
checkIfFrozen();
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
public void setGeometryIndexer(Indexer<Parsed, Processed> geometryIndexer) {
|
||||
this.geometryIndexer = geometryIndexer;
|
||||
}
|
||||
|
||||
protected Indexer<Parsed, Processed> geometryIndexer() {
|
||||
return geometryIndexer;
|
||||
}
|
||||
|
||||
public void setGeometryParser(Parser<Parsed> geometryParser) {
|
||||
this.geometryParser = geometryParser;
|
||||
}
|
||||
|
||||
protected Parser<Parsed> geometryParser() {
|
||||
return geometryParser;
|
||||
}
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> coerce;
|
||||
protected Explicit<Orientation> orientation;
|
||||
|
||||
protected AbstractShapeGeometryFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce,
|
||||
Explicit<Boolean> ignoreZValue, Explicit<Orientation> orientation, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, indexSettings, ignoreMalformed, ignoreZValue, multiFields, copyTo);
|
||||
this.coerce = coerce;
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doMerge(Mapper mergeWith) {
|
||||
super.doMerge(mergeWith);
|
||||
AbstractShapeGeometryFieldMapper gsfm = (AbstractShapeGeometryFieldMapper)mergeWith;
|
||||
if (gsfm.coerce.explicit()) {
|
||||
this.coerce = gsfm.coerce;
|
||||
}
|
||||
if (gsfm.orientation.explicit()) {
|
||||
this.orientation = gsfm.orientation;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
super.doXContentBody(builder, includeDefaults, params);
|
||||
AbstractShapeGeometryFieldType ft = (AbstractShapeGeometryFieldType)fieldType();
|
||||
if (includeDefaults || coerce.explicit()) {
|
||||
builder.field(AbstractShapeGeometryFieldMapper.Names.COERCE.getPreferredName(), coerce.value());
|
||||
}
|
||||
if (includeDefaults || ft.orientation() != Defaults.ORIENTATION.value()) {
|
||||
builder.field(Names.ORIENTATION.getPreferredName(), ft.orientation());
|
||||
}
|
||||
}
|
||||
|
||||
public Explicit<Boolean> coerce() {
|
||||
return coerce;
|
||||
}
|
||||
|
||||
public Orientation orientation() {
|
||||
return ((AbstractShapeGeometryFieldType)fieldType).orientation();
|
||||
}
|
||||
|
||||
/** parsing logic for geometry indexing */
|
||||
@Override
|
||||
public void parse(ParseContext context) throws IOException {
|
||||
AbstractShapeGeometryFieldType fieldType = (AbstractShapeGeometryFieldType)fieldType();
|
||||
|
||||
@SuppressWarnings("unchecked") Indexer<Parsed, Processed> geometryIndexer = fieldType.geometryIndexer();
|
||||
@SuppressWarnings("unchecked") Parser<Parsed> geometryParser = fieldType.geometryParser();
|
||||
try {
|
||||
Processed shape = context.parseExternalValue(geometryIndexer.processedClass());
|
||||
if (shape == null) {
|
||||
Parsed geometry = geometryParser.parse(context.parser(), this);
|
||||
if (geometry == null) {
|
||||
return;
|
||||
}
|
||||
shape = geometryIndexer.prepareForIndexing(geometry);
|
||||
}
|
||||
|
||||
List<IndexableField> fields = new ArrayList<>();
|
||||
fields.addAll(geometryIndexer.indexShape(context, shape));
|
||||
createFieldNamesField(context, fields);
|
||||
for (IndexableField field : fields) {
|
||||
context.doc().add(field);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (ignoreMalformed.value() == false) {
|
||||
throw new MapperParsingException("failed to parse field [{}] of type [{}]", e, fieldType().name(),
|
||||
fieldType().typeName());
|
||||
}
|
||||
context.addIgnoredField(fieldType().name());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -23,23 +23,20 @@ import org.apache.lucene.document.LatLonPoint;
|
|||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.geo.GeoUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
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 org.elasticsearch.index.query.VectorGeoPointShapeQueryProcessor;
|
||||
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
|
||||
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
|
||||
|
@ -57,64 +54,19 @@ import static org.elasticsearch.index.mapper.TypeParsers.parseField;
|
|||
*
|
||||
* Uses lucene 6 LatLonPoint encoding
|
||||
*/
|
||||
public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapperParser {
|
||||
public class GeoPointFieldMapper extends AbstractGeometryFieldMapper implements ArrayValueMapperParser {
|
||||
public static final String CONTENT_TYPE = "geo_point";
|
||||
|
||||
public static class Names {
|
||||
public static final String IGNORE_MALFORMED = "ignore_malformed";
|
||||
public static final ParseField IGNORE_Z_VALUE = new ParseField("ignore_z_value");
|
||||
public static final String NULL_VALUE = "null_value";
|
||||
public static class Names extends AbstractGeometryFieldMapper.Names {
|
||||
public static final ParseField NULL_VALUE = new ParseField("null_value");
|
||||
}
|
||||
|
||||
public static class Defaults {
|
||||
public static final Explicit<Boolean> IGNORE_MALFORMED = new Explicit<>(false, false);
|
||||
public static final GeoPointFieldType FIELD_TYPE = new GeoPointFieldType();
|
||||
public static final Explicit<Boolean> IGNORE_Z_VALUE = new Explicit<>(true, false);
|
||||
|
||||
static {
|
||||
FIELD_TYPE.setTokenized(false);
|
||||
FIELD_TYPE.setHasDocValues(true);
|
||||
FIELD_TYPE.setDimensions(2, Integer.BYTES);
|
||||
FIELD_TYPE.freeze();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder extends FieldMapper.Builder<Builder, GeoPointFieldMapper> {
|
||||
protected Boolean ignoreMalformed;
|
||||
private Boolean ignoreZValue;
|
||||
|
||||
public static class Builder extends AbstractGeometryFieldMapper.Builder<Builder, GeoPointFieldMapper> {
|
||||
public Builder(String name) {
|
||||
super(name, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE);
|
||||
super(name, new GeoPointFieldType(), new GeoPointFieldType());
|
||||
builder = this;
|
||||
}
|
||||
|
||||
public Builder ignoreMalformed(boolean ignoreMalformed) {
|
||||
this.ignoreMalformed = ignoreMalformed;
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreMalformed(BuilderContext context) {
|
||||
if (ignoreMalformed != null) {
|
||||
return new Explicit<>(ignoreMalformed, true);
|
||||
}
|
||||
if (context.indexSettings() != null) {
|
||||
return new Explicit<>(IGNORE_MALFORMED_SETTING.get(context.indexSettings()), false);
|
||||
}
|
||||
return GeoPointFieldMapper.Defaults.IGNORE_MALFORMED;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreZValue(BuilderContext context) {
|
||||
if (ignoreZValue != null) {
|
||||
return new Explicit<>(ignoreZValue, true);
|
||||
}
|
||||
return Defaults.IGNORE_Z_VALUE;
|
||||
}
|
||||
|
||||
public Builder ignoreZValue(final boolean ignoreZValue) {
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GeoPointFieldMapper build(BuilderContext context, String simpleName, MappedFieldType fieldType,
|
||||
MappedFieldType defaultFieldType, Settings indexSettings,
|
||||
MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
|
@ -138,13 +90,23 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
multiFieldsBuilder.build(this, context), ignoreMalformed(context),
|
||||
ignoreZValue(context), copyTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeoPointFieldType fieldType() {
|
||||
return (GeoPointFieldType)fieldType;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TypeParser implements Mapper.TypeParser {
|
||||
public static class TypeParser extends AbstractGeometryFieldMapper.TypeParser<Builder> {
|
||||
@Override
|
||||
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
|
||||
throws MapperParsingException {
|
||||
Builder builder = new GeoPointFieldMapper.Builder(name);
|
||||
protected Builder newBuilder(String name, Map<String, Object> params) {
|
||||
return new GeoPointFieldMapper.Builder(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder parse(String name, Map<String, Object> node, Map<String, Object> params, ParserContext parserContext) {
|
||||
Builder builder = super.parse(name, node, params, parserContext);
|
||||
|
||||
parseField(builder, name, node, parserContext);
|
||||
Object nullValue = null;
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
||||
|
@ -152,14 +114,7 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
String propName = entry.getKey();
|
||||
Object propNode = entry.getValue();
|
||||
|
||||
if (propName.equals(Names.IGNORE_MALFORMED)) {
|
||||
builder.ignoreMalformed(XContentMapValues.nodeBooleanValue(propNode, name + "." + Names.IGNORE_MALFORMED));
|
||||
iterator.remove();
|
||||
} else if (propName.equals(Names.IGNORE_Z_VALUE.getPreferredName())) {
|
||||
builder.ignoreZValue(XContentMapValues.nodeBooleanValue(propNode,
|
||||
name + "." + Names.IGNORE_Z_VALUE.getPreferredName()));
|
||||
iterator.remove();
|
||||
} else if (propName.equals(Names.NULL_VALUE)) {
|
||||
if (Names.NULL_VALUE.match(propName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
if (propNode == null) {
|
||||
throw new MapperParsingException("Property [null_value] cannot be null.");
|
||||
}
|
||||
|
@ -169,8 +124,8 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
}
|
||||
|
||||
if (nullValue != null) {
|
||||
boolean ignoreZValue = builder.ignoreZValue == null ? Defaults.IGNORE_Z_VALUE.value() : builder.ignoreZValue;
|
||||
boolean ignoreMalformed = builder.ignoreMalformed == null ? Defaults.IGNORE_MALFORMED.value() : builder.ignoreMalformed;
|
||||
boolean ignoreZValue = builder.ignoreZValue().value();
|
||||
boolean ignoreMalformed = builder.ignoreMalformed().value();
|
||||
GeoPoint point = GeoUtils.parseGeoPoint(nullValue, ignoreZValue);
|
||||
if (ignoreMalformed == false) {
|
||||
if (point.lat() > 90.0 || point.lat() < -90.0) {
|
||||
|
@ -188,27 +143,15 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
}
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreMalformed;
|
||||
protected Explicit<Boolean> ignoreZValue;
|
||||
|
||||
public GeoPointFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Settings indexSettings, MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> ignoreZValue, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo);
|
||||
this.ignoreMalformed = ignoreMalformed;
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
super(simpleName, fieldType, defaultFieldType, indexSettings, ignoreMalformed, ignoreZValue, multiFields, copyTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doMerge(Mapper mergeWith) {
|
||||
super.doMerge(mergeWith);
|
||||
GeoPointFieldMapper gpfmMergeWith = (GeoPointFieldMapper) mergeWith;
|
||||
if (gpfmMergeWith.ignoreMalformed.explicit()) {
|
||||
this.ignoreMalformed = gpfmMergeWith.ignoreMalformed;
|
||||
}
|
||||
if (gpfmMergeWith.ignoreZValue.explicit()) {
|
||||
this.ignoreZValue = gpfmMergeWith.ignoreZValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -216,13 +159,11 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
return CONTENT_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException {
|
||||
throw new UnsupportedOperationException("Parsing is implemented in parse(), this method should NEVER be called");
|
||||
}
|
||||
|
||||
public static class GeoPointFieldType extends AbstractSearchableGeometryFieldType {
|
||||
public static class GeoPointFieldType extends AbstractGeometryFieldType {
|
||||
public GeoPointFieldType() {
|
||||
super();
|
||||
setHasDocValues(true);
|
||||
setDimensions(2, Integer.BYTES);
|
||||
}
|
||||
|
||||
GeoPointFieldType(GeoPointFieldType ref) {
|
||||
|
@ -255,15 +196,9 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
if (hasDocValues()) {
|
||||
return new DocValuesFieldExistsQuery(name());
|
||||
} else {
|
||||
return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name()));
|
||||
return super.existsQuery(context);
|
||||
}
|
||||
}
|
||||
|
||||
@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() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
protected void parse(ParseContext context, GeoPoint point) throws IOException {
|
||||
|
@ -364,24 +299,13 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
public void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
super.doXContentBody(builder, includeDefaults, params);
|
||||
if (includeDefaults || ignoreMalformed.explicit()) {
|
||||
builder.field(Names.IGNORE_MALFORMED, ignoreMalformed.value());
|
||||
}
|
||||
if (includeDefaults || ignoreZValue.explicit()) {
|
||||
builder.field(Names.IGNORE_Z_VALUE.getPreferredName(), ignoreZValue.value());
|
||||
}
|
||||
|
||||
if (includeDefaults || fieldType().nullValue() != null) {
|
||||
builder.field(Names.NULL_VALUE, fieldType().nullValue());
|
||||
builder.field(Names.NULL_VALUE.getPreferredName(), fieldType().nullValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Explicit<Boolean> ignoreZValue() {
|
||||
return ignoreZValue;
|
||||
}
|
||||
|
||||
private boolean isNormalizable(double coord) {
|
||||
return Double.isNaN(coord) == false && Double.isInfinite(coord) == false;
|
||||
}
|
||||
|
|
|
@ -48,10 +48,11 @@ import java.util.Map;
|
|||
* <p>
|
||||
* "field" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0))
|
||||
*/
|
||||
public class GeoShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geometry> {
|
||||
public class GeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper<Geometry, Geometry> {
|
||||
public static final String CONTENT_TYPE = "geo_shape";
|
||||
|
||||
public static class Builder extends AbstractGeometryFieldMapper.Builder<AbstractGeometryFieldMapper.Builder, GeoShapeFieldMapper> {
|
||||
public static class Builder extends AbstractShapeGeometryFieldMapper.Builder<AbstractShapeGeometryFieldMapper.Builder,
|
||||
GeoShapeFieldMapper> {
|
||||
public Builder(String name) {
|
||||
super (name, new GeoShapeFieldType(), new GeoShapeFieldType());
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ public class GeoShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, G
|
|||
public GeoShapeFieldMapper build(BuilderContext context) {
|
||||
setupFieldType(context);
|
||||
return new GeoShapeFieldMapper(name, fieldType, defaultFieldType, ignoreMalformed(context), coerce(context),
|
||||
ignoreZValue(), context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
|
||||
ignoreZValue(), orientation(), context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,9 +79,10 @@ public class GeoShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, G
|
|||
}
|
||||
}
|
||||
|
||||
public static class GeoShapeFieldType extends AbstractGeometryFieldType<Geometry, Geometry> {
|
||||
public static class GeoShapeFieldType extends AbstractShapeGeometryFieldType<Geometry, Geometry> {
|
||||
public GeoShapeFieldType() {
|
||||
super();
|
||||
setDimensions(7, 4, Integer.BYTES);
|
||||
}
|
||||
|
||||
protected GeoShapeFieldType(GeoShapeFieldType ref) {
|
||||
|
@ -98,10 +100,10 @@ public class GeoShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, G
|
|||
}
|
||||
}
|
||||
|
||||
public static final class TypeParser extends AbstractGeometryFieldMapper.TypeParser {
|
||||
public static final class TypeParser extends AbstractShapeGeometryFieldMapper.TypeParser {
|
||||
|
||||
@Override
|
||||
protected AbstractGeometryFieldMapper.Builder newBuilder(String name, Map<String, Object> params) {
|
||||
protected AbstractShapeGeometryFieldMapper.Builder newBuilder(String name, Map<String, Object> params) {
|
||||
if (params.containsKey(DEPRECATED_PARAMETERS_KEY)) {
|
||||
return new LegacyGeoShapeFieldMapper.Builder(name,
|
||||
(LegacyGeoShapeFieldMapper.DeprecatedParameters)params.get(DEPRECATED_PARAMETERS_KEY));
|
||||
|
@ -112,9 +114,9 @@ public class GeoShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, G
|
|||
|
||||
public GeoShapeFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce,
|
||||
Explicit<Boolean> ignoreZValue, Settings indexSettings,
|
||||
Explicit<Boolean> ignoreZValue, Explicit<ShapeBuilder.Orientation> orientation, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, indexSettings,
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, orientation, indexSettings,
|
||||
multiFields, copyTo);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ import static org.elasticsearch.common.geo.GeoUtils.normalizePoint;
|
|||
/**
|
||||
* Utility class that converts geometries into Lucene-compatible form for indexing in a geo_shape field.
|
||||
*/
|
||||
public class GeoShapeIndexer implements AbstractGeometryFieldMapper.Indexer<Geometry, Geometry> {
|
||||
public class GeoShapeIndexer implements AbstractShapeGeometryFieldMapper.Indexer<Geometry, Geometry> {
|
||||
|
||||
private final boolean orientation;
|
||||
private final String name;
|
||||
|
|
|
@ -74,7 +74,7 @@ import java.util.Objects;
|
|||
* @deprecated use {@link GeoShapeFieldMapper}
|
||||
*/
|
||||
@Deprecated
|
||||
public class LegacyGeoShapeFieldMapper extends AbstractGeometryFieldMapper<ShapeBuilder<?, ?, ?>, Shape> {
|
||||
public class LegacyGeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper<ShapeBuilder<?, ?, ?>, Shape> {
|
||||
|
||||
public static final String CONTENT_TYPE = "geo_shape";
|
||||
|
||||
|
@ -178,7 +178,7 @@ public class LegacyGeoShapeFieldMapper extends AbstractGeometryFieldMapper<Shape
|
|||
private static final Logger logger = LogManager.getLogger(LegacyGeoShapeFieldMapper.class);
|
||||
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(logger);
|
||||
|
||||
public static class Builder extends AbstractGeometryFieldMapper.Builder<AbstractGeometryFieldMapper.Builder,
|
||||
public static class Builder extends AbstractShapeGeometryFieldMapper.Builder<AbstractShapeGeometryFieldMapper.Builder,
|
||||
LegacyGeoShapeFieldMapper> {
|
||||
|
||||
DeprecatedParameters deprecatedParameters;
|
||||
|
@ -299,7 +299,7 @@ public class LegacyGeoShapeFieldMapper extends AbstractGeometryFieldMapper<Shape
|
|||
}
|
||||
}
|
||||
|
||||
public static final class GeoShapeFieldType extends AbstractGeometryFieldType {
|
||||
public static final class GeoShapeFieldType extends AbstractShapeGeometryFieldType {
|
||||
|
||||
private String tree = DeprecatedParameters.Defaults.TREE;
|
||||
private SpatialStrategy strategy = DeprecatedParameters.Defaults.STRATEGY;
|
||||
|
@ -474,7 +474,7 @@ public class LegacyGeoShapeFieldMapper extends AbstractGeometryFieldMapper<Shape
|
|||
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce, Explicit<Orientation> orientation,
|
||||
Explicit<Boolean> ignoreZValue, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, indexSettings,
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, orientation, indexSettings,
|
||||
multiFields, copyTo);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class LegacyGeoShapeIndexer implements AbstractGeometryFieldMapper.Indexer<ShapeBuilder<?, ?, ?>, Shape> {
|
||||
public class LegacyGeoShapeIndexer implements AbstractShapeGeometryFieldMapper.Indexer<ShapeBuilder<?, ?, ?>, Shape> {
|
||||
|
||||
private LegacyGeoShapeFieldMapper.GeoShapeFieldType fieldType;
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.elasticsearch.common.logging.DeprecationLogger;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.GeoPointFieldMapper;
|
||||
import org.elasticsearch.index.mapper.GeoShapeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
|
@ -220,8 +220,8 @@ public class GeoShapeQueryBuilder extends AbstractGeometryQueryBuilder<GeoShapeQ
|
|||
+ String.join(",", validContentTypes()) + "]");
|
||||
}
|
||||
|
||||
final AbstractSearchableGeometryFieldType ft =
|
||||
(AbstractSearchableGeometryFieldType) fieldType;
|
||||
final AbstractGeometryFieldType ft =
|
||||
(AbstractGeometryFieldType) fieldType;
|
||||
return new ConstantScoreQuery(ft.geometryQueryBuilder().process(shape, fieldName, strategy, relation, context));
|
||||
}
|
||||
|
||||
|
|
|
@ -52,8 +52,8 @@ import org.elasticsearch.geometry.MultiPolygon;
|
|||
import org.elasticsearch.geometry.Point;
|
||||
import org.elasticsearch.geometry.Polygon;
|
||||
import org.elasticsearch.geometry.Rectangle;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType.QueryProcessor;
|
||||
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper;
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
import org.locationtech.spatial4j.shape.Shape;
|
||||
|
@ -63,11 +63,11 @@ import java.util.List;
|
|||
|
||||
import static org.elasticsearch.search.SearchService.ALLOW_EXPENSIVE_QUERIES;
|
||||
|
||||
public class LegacyGeoShapeQueryProcessor implements AbstractSearchableGeometryFieldType.QueryProcessor {
|
||||
public class LegacyGeoShapeQueryProcessor implements QueryProcessor {
|
||||
|
||||
private AbstractGeometryFieldMapper.AbstractGeometryFieldType ft;
|
||||
private AbstractShapeGeometryFieldMapper.AbstractShapeGeometryFieldType ft;
|
||||
|
||||
public LegacyGeoShapeQueryProcessor(AbstractGeometryFieldMapper.AbstractGeometryFieldType ft) {
|
||||
public LegacyGeoShapeQueryProcessor(AbstractShapeGeometryFieldMapper.AbstractShapeGeometryFieldType ft) {
|
||||
this.ft = ft;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,13 +41,13 @@ import org.elasticsearch.geometry.Point;
|
|||
import org.elasticsearch.geometry.Polygon;
|
||||
import org.elasticsearch.geometry.Rectangle;
|
||||
import org.elasticsearch.geometry.ShapeType;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType.QueryProcessor;
|
||||
import org.elasticsearch.index.mapper.GeoPointFieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class VectorGeoPointShapeQueryProcessor implements AbstractSearchableGeometryFieldType.QueryProcessor {
|
||||
public class VectorGeoPointShapeQueryProcessor implements QueryProcessor {
|
||||
|
||||
@Override
|
||||
public Query process(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context) {
|
||||
|
|
|
@ -40,14 +40,14 @@ import org.elasticsearch.geometry.MultiPolygon;
|
|||
import org.elasticsearch.geometry.Point;
|
||||
import org.elasticsearch.geometry.Polygon;
|
||||
import org.elasticsearch.geometry.Rectangle;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType.QueryProcessor;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class VectorGeoShapeQueryProcessor implements AbstractSearchableGeometryFieldType.QueryProcessor {
|
||||
public class VectorGeoShapeQueryProcessor implements QueryProcessor {
|
||||
|
||||
@Override
|
||||
public Query process(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context) {
|
||||
|
|
|
@ -88,7 +88,7 @@ public class ExternalMapper extends FieldMapper {
|
|||
BinaryFieldMapper binMapper = binBuilder.build(context);
|
||||
BooleanFieldMapper boolMapper = boolBuilder.build(context);
|
||||
GeoPointFieldMapper pointMapper = latLonPointBuilder.build(context);
|
||||
AbstractGeometryFieldMapper shapeMapper = (context.indexCreatedVersion().before(Version.V_6_6_0))
|
||||
AbstractShapeGeometryFieldMapper shapeMapper = (context.indexCreatedVersion().before(Version.V_6_6_0))
|
||||
? legacyShapeBuilder.build(context)
|
||||
: shapeBuilder.build(context);
|
||||
FieldMapper stringMapper = (FieldMapper)stringBuilder.build(context);
|
||||
|
@ -154,13 +154,13 @@ public class ExternalMapper extends FieldMapper {
|
|||
private BinaryFieldMapper binMapper;
|
||||
private BooleanFieldMapper boolMapper;
|
||||
private GeoPointFieldMapper pointMapper;
|
||||
private AbstractGeometryFieldMapper shapeMapper;
|
||||
private AbstractShapeGeometryFieldMapper shapeMapper;
|
||||
private FieldMapper stringMapper;
|
||||
|
||||
public ExternalMapper(String simpleName, MappedFieldType fieldType,
|
||||
String generatedValue, String mapperName,
|
||||
BinaryFieldMapper binMapper, BooleanFieldMapper boolMapper, GeoPointFieldMapper pointMapper,
|
||||
AbstractGeometryFieldMapper shapeMapper, FieldMapper stringMapper, Settings indexSettings,
|
||||
AbstractShapeGeometryFieldMapper shapeMapper, FieldMapper stringMapper, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, new ExternalFieldType(), indexSettings, multiFields, copyTo);
|
||||
this.generatedValue = generatedValue;
|
||||
|
@ -218,7 +218,8 @@ public class ExternalMapper extends FieldMapper {
|
|||
BinaryFieldMapper binMapperUpdate = (BinaryFieldMapper) binMapper.updateFieldType(fullNameToFieldType);
|
||||
BooleanFieldMapper boolMapperUpdate = (BooleanFieldMapper) boolMapper.updateFieldType(fullNameToFieldType);
|
||||
GeoPointFieldMapper pointMapperUpdate = (GeoPointFieldMapper) pointMapper.updateFieldType(fullNameToFieldType);
|
||||
AbstractGeometryFieldMapper shapeMapperUpdate = (AbstractGeometryFieldMapper) shapeMapper.updateFieldType(fullNameToFieldType);
|
||||
AbstractShapeGeometryFieldMapper shapeMapperUpdate =
|
||||
(AbstractShapeGeometryFieldMapper) shapeMapper.updateFieldType(fullNameToFieldType);
|
||||
TextFieldMapper stringMapperUpdate = (TextFieldMapper) stringMapper.updateFieldType(fullNameToFieldType);
|
||||
if (update == this
|
||||
&& multiFieldsUpdate == multiFields
|
||||
|
|
|
@ -387,7 +387,7 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase {
|
|||
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("properties").startObject("location")
|
||||
.field("type", "geo_point")
|
||||
.field(NULL_VALUE, "1,2")
|
||||
.field(NULL_VALUE.getPreferredName(), "1,2")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject());
|
||||
|
||||
|
@ -439,8 +439,8 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase {
|
|||
.startObject("properties").startObject("location")
|
||||
.field("type", "geo_point")
|
||||
.field(IGNORE_Z_VALUE.getPreferredName(), false)
|
||||
.field(IGNORE_MALFORMED, true)
|
||||
.field(NULL_VALUE, "91,181")
|
||||
.field(IGNORE_MALFORMED.getPreferredName(), true)
|
||||
.field(NULL_VALUE.getPreferredName(), "91,181")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject());
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ public class GeoShapeFieldMapperTests extends ESSingleNodeTestCase {
|
|||
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
|
||||
String serialized = toXContentString((GeoShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
|
||||
assertTrue(serialized, serialized.contains("\"orientation\":\"" +
|
||||
AbstractGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
AbstractShapeGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -304,7 +304,8 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
|
|||
MatchQueryBuilder query = new MatchQueryBuilder(GEO_POINT_FIELD_NAME, "2,3");
|
||||
QueryShardContext context = createShardContext();
|
||||
QueryShardException e = expectThrows(QueryShardException.class, () -> query.toQuery(context));
|
||||
assertEquals("Geo fields do not support exact searching, use dedicated geo queries instead: [mapped_geo_point]", e.getMessage());
|
||||
assertEquals("Geometry fields do not support exact searching, use dedicated geometry queries instead: " +
|
||||
"[mapped_geo_point]", e.getMessage());
|
||||
query.lenient(true);
|
||||
query.toQuery(context); // no exception
|
||||
}
|
||||
|
|
|
@ -827,8 +827,8 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
|
|||
QueryShardContext context = createShardContext();
|
||||
QueryShardException e = expectThrows(QueryShardException.class,
|
||||
() -> query.toQuery(context));
|
||||
assertEquals("Geo fields do not support exact searching, use dedicated geo queries instead: [mapped_geo_point]",
|
||||
e.getMessage());
|
||||
assertEquals("Geometry fields do not support exact searching, use dedicated geometry queries instead: "
|
||||
+ "[mapped_geo_point]", e.getMessage());
|
||||
query.lenient(true);
|
||||
query.toQuery(context); // no exception
|
||||
}
|
||||
|
|
|
@ -138,8 +138,8 @@ public class TermQueryBuilderTests extends AbstractTermQueryTestCase<TermQueryBu
|
|||
TermQueryBuilder query = new TermQueryBuilder(GEO_POINT_FIELD_NAME, "2,3");
|
||||
QueryShardContext context = createShardContext();
|
||||
QueryShardException e = expectThrows(QueryShardException.class, () -> query.toQuery(context));
|
||||
assertEquals("Geo fields do not support exact searching, use dedicated geo queries instead: [mapped_geo_point]",
|
||||
e.getMessage());
|
||||
assertEquals("Geometry fields do not support exact searching, "
|
||||
+ "use dedicated geometry queries instead: [mapped_geo_point]", e.getMessage());
|
||||
}
|
||||
|
||||
public void testParseFailsWithMultipleFields() throws IOException {
|
||||
|
|
|
@ -293,8 +293,8 @@ public class TermsQueryBuilderTests extends AbstractQueryTestCase<TermsQueryBuil
|
|||
QueryShardContext context = createShardContext();
|
||||
QueryShardException e = expectThrows(QueryShardException.class,
|
||||
() -> query.toQuery(context));
|
||||
assertEquals("Geo fields do not support exact searching, use dedicated geo queries instead: [mapped_geo_point]",
|
||||
e.getMessage());
|
||||
assertEquals("Geometry fields do not support exact searching, use dedicated geometry queries instead: "
|
||||
+ "[mapped_geo_point]", e.getMessage());
|
||||
}
|
||||
|
||||
public void testSerializationFailsUnlessFetched() throws IOException {
|
||||
|
|
|
@ -129,7 +129,7 @@ public class GeoDistanceSortBuilderTests extends AbstractSortTestCase<GeoDistanc
|
|||
|
||||
@Override
|
||||
protected MappedFieldType provideMappedFieldType(String name) {
|
||||
MappedFieldType clone = GeoPointFieldMapper.Defaults.FIELD_TYPE.clone();
|
||||
MappedFieldType clone = new GeoPointFieldMapper.GeoPointFieldType();
|
||||
clone.setName(name);
|
||||
return clone;
|
||||
}
|
||||
|
|
|
@ -19,17 +19,15 @@ import org.elasticsearch.common.Explicit;
|
|||
import org.elasticsearch.common.geo.GeometryParser;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
|
||||
import org.elasticsearch.index.mapper.GeoShapeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.GeoShapeIndexer;
|
||||
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.Mapper;
|
||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.mapper.TypeParsers;
|
||||
|
@ -40,7 +38,6 @@ import org.elasticsearch.xpack.spatial.index.fielddata.AbstractLatLonShapeDVInde
|
|||
import org.elasticsearch.xpack.spatial.index.fielddata.CentroidCalculator;
|
||||
import org.elasticsearch.xpack.spatial.search.aggregations.support.GeoShapeValuesSourceType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -74,16 +71,8 @@ public class GeoShapeWithDocValuesFieldMapper extends GeoShapeFieldMapper {
|
|||
|
||||
private Explicit<Boolean> docValues;
|
||||
|
||||
@Override
|
||||
public void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
super.doXContentBody(builder, includeDefaults, params);
|
||||
if (includeDefaults || docValues.explicit()) {
|
||||
builder.field(TypeParsers.DOC_VALUES, docValues.value());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static class Builder extends AbstractGeometryFieldMapper.Builder<AbstractGeometryFieldMapper.Builder,
|
||||
public static class Builder extends AbstractShapeGeometryFieldMapper.Builder<AbstractShapeGeometryFieldMapper.Builder,
|
||||
GeoShapeWithDocValuesFieldMapper> {
|
||||
public Builder(String name) {
|
||||
super (name, new GeoShapeWithDocValuesFieldType(), new GeoShapeWithDocValuesFieldType());
|
||||
|
@ -93,7 +82,7 @@ public class GeoShapeWithDocValuesFieldMapper extends GeoShapeFieldMapper {
|
|||
public GeoShapeWithDocValuesFieldMapper build(BuilderContext context) {
|
||||
setupFieldType(context);
|
||||
return new GeoShapeWithDocValuesFieldMapper(name, fieldType, defaultFieldType, ignoreMalformed(context), coerce(context),
|
||||
ignoreZValue(), docValues(), context.indexSettings(),
|
||||
ignoreZValue(), orientation(), docValues(), context.indexSettings(),
|
||||
multiFieldsBuilder.build(this, context), copyTo);
|
||||
}
|
||||
|
||||
|
@ -185,11 +174,11 @@ public class GeoShapeWithDocValuesFieldMapper extends GeoShapeFieldMapper {
|
|||
}
|
||||
}
|
||||
|
||||
public static final class TypeParser extends AbstractGeometryFieldMapper.TypeParser {
|
||||
public static final class TypeParser extends AbstractShapeGeometryFieldMapper.TypeParser {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected AbstractGeometryFieldMapper.Builder newBuilder(String name, Map<String, Object> params) {
|
||||
protected AbstractShapeGeometryFieldMapper.Builder newBuilder(String name, Map<String, Object> params) {
|
||||
if (params.containsKey(DEPRECATED_PARAMETERS_KEY)) {
|
||||
return new LegacyGeoShapeFieldMapper.Builder(name,
|
||||
(LegacyGeoShapeFieldMapper.DeprecatedParameters)params.get(DEPRECATED_PARAMETERS_KEY));
|
||||
|
@ -199,8 +188,9 @@ public class GeoShapeWithDocValuesFieldMapper extends GeoShapeFieldMapper {
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||
AbstractGeometryFieldMapper.Builder builder = (AbstractGeometryFieldMapper.Builder) super.parse(name, node, parserContext);
|
||||
public AbstractShapeGeometryFieldMapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
|
||||
throws MapperParsingException {
|
||||
AbstractShapeGeometryFieldMapper.Builder builder = super.parse(name, node, parserContext);
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<String, Object> entry = iterator.next();
|
||||
|
@ -221,9 +211,10 @@ public class GeoShapeWithDocValuesFieldMapper extends GeoShapeFieldMapper {
|
|||
|
||||
public GeoShapeWithDocValuesFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce,
|
||||
Explicit<Boolean> ignoreZValue, Explicit<Boolean> docValues, Settings indexSettings,
|
||||
Explicit<Boolean> ignoreZValue, Explicit<ShapeBuilder.Orientation> orientation,
|
||||
Explicit<Boolean> docValues, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, indexSettings,
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, orientation, indexSettings,
|
||||
multiFields, copyTo);
|
||||
this.docValues = docValues;
|
||||
}
|
||||
|
|
|
@ -10,28 +10,19 @@ import org.apache.lucene.document.XYDocValuesField;
|
|||
import org.apache.lucene.document.XYPointField;
|
||||
import org.apache.lucene.index.IndexOptions;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.DocValuesFieldExistsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ArrayValueMapperParser;
|
||||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
|
||||
import org.elasticsearch.index.mapper.GeoPointFieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.Mapper;
|
||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
import org.elasticsearch.xpack.spatial.common.CartesianPoint;
|
||||
import org.elasticsearch.xpack.spatial.index.query.ShapeQueryPointProcessor;
|
||||
|
||||
|
@ -49,63 +40,19 @@ import static org.elasticsearch.index.mapper.TypeParsers.parseField;
|
|||
*
|
||||
* Uses lucene 8 XYPoint encoding
|
||||
*/
|
||||
public class PointFieldMapper extends FieldMapper implements ArrayValueMapperParser {
|
||||
public class PointFieldMapper extends AbstractGeometryFieldMapper implements ArrayValueMapperParser {
|
||||
public static final String CONTENT_TYPE = "point";
|
||||
|
||||
public static class Names {
|
||||
public static final ParseField IGNORE_MALFORMED = new ParseField("ignore_malformed");
|
||||
public static final ParseField IGNORE_Z_VALUE = new ParseField("ignore_z_value");
|
||||
public static class Names extends AbstractGeometryFieldMapper.Names {
|
||||
public static final ParseField NULL_VALUE = new ParseField("null_value");
|
||||
}
|
||||
|
||||
public static class Defaults {
|
||||
public static final Explicit<Boolean> IGNORE_MALFORMED = new Explicit<>(false, false);
|
||||
public static final PointFieldType FIELD_TYPE = new PointFieldType();
|
||||
public static final Explicit<Boolean> IGNORE_Z_VALUE = new Explicit<>(true, false);
|
||||
|
||||
static {
|
||||
FIELD_TYPE.setTokenized(false);
|
||||
FIELD_TYPE.setHasDocValues(true);
|
||||
FIELD_TYPE.setDimensions(2, Integer.BYTES);
|
||||
FIELD_TYPE.freeze();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder extends FieldMapper.Builder<Builder, PointFieldMapper> {
|
||||
protected Boolean ignoreMalformed;
|
||||
private Boolean ignoreZValue;
|
||||
|
||||
public static class Builder extends AbstractGeometryFieldMapper.Builder<Builder, PointFieldMapper> {
|
||||
public Builder(String name) {
|
||||
super(name, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE);
|
||||
super(name, new PointFieldType(), new PointFieldType());
|
||||
builder = this;
|
||||
}
|
||||
|
||||
public Builder ignoreMalformed(boolean ignoreMalformed) {
|
||||
this.ignoreMalformed = ignoreMalformed;
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreMalformed(BuilderContext context) {
|
||||
if (ignoreMalformed != null) {
|
||||
return new Explicit<>(ignoreMalformed, true);
|
||||
}
|
||||
if (context.indexSettings() != null) {
|
||||
return new Explicit<>(IGNORE_MALFORMED_SETTING.get(context.indexSettings()), false);
|
||||
}
|
||||
return PointFieldMapper.Defaults.IGNORE_MALFORMED;
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreZValue(BuilderContext context) {
|
||||
if (ignoreZValue != null) {
|
||||
return new Explicit<>(ignoreZValue, true);
|
||||
}
|
||||
return PointFieldMapper.Defaults.IGNORE_Z_VALUE;
|
||||
}
|
||||
|
||||
public PointFieldMapper.Builder ignoreZValue(final boolean ignoreZValue) {
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
return this;
|
||||
}
|
||||
public PointFieldMapper build(BuilderContext context, String simpleName, MappedFieldType fieldType,
|
||||
MappedFieldType defaultFieldType, Settings indexSettings,
|
||||
MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
|
@ -134,12 +81,16 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
}
|
||||
}
|
||||
|
||||
public static class TypeParser implements Mapper.TypeParser {
|
||||
public static class TypeParser extends AbstractGeometryFieldMapper.TypeParser<Builder> {
|
||||
@Override
|
||||
protected Builder newBuilder(String name, Map<String, Object> params) {
|
||||
return new PointFieldMapper.Builder(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext)
|
||||
throws MapperParsingException {
|
||||
Builder builder = new PointFieldMapper.Builder(name);
|
||||
public Builder parse(String name, Map<String, Object> node, Map<String, Object> params, ParserContext parserContext) {
|
||||
Builder builder = super.parse(name, node, params, parserContext);
|
||||
parseField(builder, name, node, parserContext);
|
||||
Object nullValue = null;
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
|
||||
|
@ -147,14 +98,7 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
String propName = entry.getKey();
|
||||
Object propNode = entry.getValue();
|
||||
|
||||
if (propName.equals(Names.IGNORE_MALFORMED.getPreferredName())) {
|
||||
builder.ignoreMalformed(XContentMapValues.nodeBooleanValue(propNode, name + "." + Names.IGNORE_MALFORMED));
|
||||
iterator.remove();
|
||||
} else if (propName.equals(PointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName())) {
|
||||
builder.ignoreZValue(XContentMapValues.nodeBooleanValue(propNode,
|
||||
name + "." + PointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName()));
|
||||
iterator.remove();
|
||||
} else if (propName.equals(Names.NULL_VALUE.getPreferredName())) {
|
||||
if (Names.NULL_VALUE.match(propName, LoggingDeprecationHandler.INSTANCE)) {
|
||||
if (propNode == null) {
|
||||
throw new MapperParsingException("Property [null_value] cannot be null.");
|
||||
}
|
||||
|
@ -164,10 +108,8 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
}
|
||||
|
||||
if (nullValue != null) {
|
||||
boolean ignoreMalformed = builder.ignoreMalformed == null ?
|
||||
Defaults.IGNORE_MALFORMED.value() : builder.ignoreMalformed;
|
||||
boolean ignoreZValue = builder.ignoreZValue == null ?
|
||||
Defaults.IGNORE_Z_VALUE.value() : builder.ignoreZValue;
|
||||
boolean ignoreMalformed = builder.ignoreMalformed().value();
|
||||
boolean ignoreZValue = builder.ignoreZValue().value();
|
||||
CartesianPoint point = CartesianPoint.parsePoint(nullValue, ignoreZValue);
|
||||
if (ignoreMalformed == false) {
|
||||
if (Float.isFinite(point.getX()) == false) {
|
||||
|
@ -183,27 +125,15 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
}
|
||||
}
|
||||
|
||||
protected Explicit<Boolean> ignoreMalformed;
|
||||
protected Explicit<Boolean> ignoreZValue;
|
||||
|
||||
public PointFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Settings indexSettings, MultiFields multiFields, Explicit<Boolean> ignoreMalformed,
|
||||
Explicit<Boolean> ignoreZValue, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo);
|
||||
this.ignoreMalformed = ignoreMalformed;
|
||||
this.ignoreZValue = ignoreZValue;
|
||||
super(simpleName, fieldType, defaultFieldType, indexSettings, ignoreMalformed, ignoreZValue, multiFields, copyTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doMerge(Mapper mergeWith) {
|
||||
super.doMerge(mergeWith);
|
||||
PointFieldMapper gpfmMergeWith = (PointFieldMapper) mergeWith;
|
||||
if (gpfmMergeWith.ignoreMalformed.explicit()) {
|
||||
this.ignoreMalformed = gpfmMergeWith.ignoreMalformed;
|
||||
}
|
||||
if (gpfmMergeWith.ignoreZValue.explicit()) {
|
||||
this.ignoreZValue = gpfmMergeWith.ignoreZValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -211,13 +141,11 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
return CONTENT_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException {
|
||||
throw new UnsupportedOperationException("Parsing is implemented in parse(), this method should NEVER be called");
|
||||
}
|
||||
|
||||
public static class PointFieldType extends AbstractSearchableGeometryFieldType {
|
||||
public static class PointFieldType extends AbstractGeometryFieldType {
|
||||
public PointFieldType() {
|
||||
super();
|
||||
setHasDocValues(true);
|
||||
setDimensions(2, Integer.BYTES);
|
||||
}
|
||||
|
||||
PointFieldType(PointFieldType ref) {
|
||||
|
@ -233,21 +161,6 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
public MappedFieldType clone() {
|
||||
return new PointFieldType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query existsQuery(QueryShardContext context) {
|
||||
if (hasDocValues()) {
|
||||
return new DocValuesFieldExistsQuery(name());
|
||||
} else {
|
||||
return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query termQuery(Object value, QueryShardContext context) {
|
||||
throw new QueryShardException(context, "Spatial fields do not support exact searching, " +
|
||||
"use dedicated spatial queries instead: [" + name() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
protected void parse(ParseContext context, CartesianPoint point) throws IOException {
|
||||
|
@ -334,20 +247,10 @@ public class PointFieldMapper extends FieldMapper implements ArrayValueMapperPar
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
public void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
|
||||
super.doXContentBody(builder, includeDefaults, params);
|
||||
if (includeDefaults || ignoreMalformed.explicit()) {
|
||||
builder.field(Names.IGNORE_MALFORMED.getPreferredName(), ignoreMalformed.value());
|
||||
}
|
||||
if (includeDefaults || ignoreZValue.explicit()) {
|
||||
builder.field(GeoPointFieldMapper.Names.IGNORE_Z_VALUE.getPreferredName(), ignoreZValue.value());
|
||||
}
|
||||
if (includeDefaults || fieldType().nullValue() != null) {
|
||||
builder.field(Names.NULL_VALUE.getPreferredName(), fieldType().nullValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Explicit<Boolean> ignoreZValue() {
|
||||
return ignoreZValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ package org.elasticsearch.xpack.spatial.index.mapper;
|
|||
import org.apache.lucene.document.XYShape;
|
||||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.geo.GeometryParser;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||
import org.elasticsearch.xpack.spatial.index.query.ShapeQueryProcessor;
|
||||
|
@ -34,15 +34,16 @@ import java.util.Map;
|
|||
* <p>
|
||||
* "field" : "POLYGON ((1050.0 -1000.0, 1051.0 -1000.0, 1051.0 -1001.0, 1050.0 -1001.0, 1050.0 -1000.0))
|
||||
*/
|
||||
public class ShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geometry> {
|
||||
public class ShapeFieldMapper extends AbstractShapeGeometryFieldMapper<Geometry, Geometry> {
|
||||
public static final String CONTENT_TYPE = "shape";
|
||||
|
||||
public static class Defaults extends AbstractGeometryFieldMapper.Defaults {
|
||||
public static class Defaults extends AbstractShapeGeometryFieldMapper.Defaults {
|
||||
public static final ShapeFieldType FIELD_TYPE = new ShapeFieldType();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static class Builder extends AbstractGeometryFieldMapper.Builder<AbstractGeometryFieldMapper.Builder, ShapeFieldMapper> {
|
||||
public static class Builder extends AbstractShapeGeometryFieldMapper.Builder<AbstractShapeGeometryFieldMapper.Builder,
|
||||
ShapeFieldMapper> {
|
||||
|
||||
public Builder(String name) {
|
||||
super(name, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE);
|
||||
|
@ -53,7 +54,7 @@ public class ShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geom
|
|||
public ShapeFieldMapper build(BuilderContext context) {
|
||||
setupFieldType(context);
|
||||
return new ShapeFieldMapper(name, fieldType, defaultFieldType, ignoreMalformed(context), coerce(context),
|
||||
ignoreZValue(), context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
|
||||
ignoreZValue(), orientation(), context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +67,7 @@ public class ShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geom
|
|||
protected void setupFieldType(BuilderContext context) {
|
||||
super.setupFieldType(context);
|
||||
|
||||
GeometryParser geometryParser = new GeometryParser(orientation == ShapeBuilder.Orientation.RIGHT,
|
||||
GeometryParser geometryParser = new GeometryParser(orientation == Orientation.RIGHT,
|
||||
coerce(context).value(), ignoreZValue().value());
|
||||
|
||||
fieldType().setGeometryIndexer(new ShapeIndexer(fieldType().name()));
|
||||
|
@ -75,7 +76,7 @@ public class ShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geom
|
|||
}
|
||||
}
|
||||
|
||||
public static class TypeParser extends AbstractGeometryFieldMapper.TypeParser {
|
||||
public static class TypeParser extends AbstractShapeGeometryFieldMapper.TypeParser {
|
||||
@Override
|
||||
protected boolean parseXContentParameters(String name, Map.Entry<String, Object> entry,
|
||||
Map<String, Object> params) throws MapperParsingException {
|
||||
|
@ -89,9 +90,10 @@ public class ShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geom
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static final class ShapeFieldType extends AbstractGeometryFieldType {
|
||||
public static final class ShapeFieldType extends AbstractShapeGeometryFieldType {
|
||||
public ShapeFieldType() {
|
||||
super();
|
||||
setDimensions(7, 4, Integer.BYTES);
|
||||
}
|
||||
|
||||
public ShapeFieldType(ShapeFieldType ref) {
|
||||
|
@ -116,9 +118,9 @@ public class ShapeFieldMapper extends AbstractGeometryFieldMapper<Geometry, Geom
|
|||
|
||||
public ShapeFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType,
|
||||
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce,
|
||||
Explicit<Boolean> ignoreZValue, Settings indexSettings,
|
||||
MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, indexSettings,
|
||||
Explicit<Boolean> ignoreZValue, Explicit<Orientation> orientation,
|
||||
Settings indexSettings, MultiFields multiFields, CopyTo copyTo) {
|
||||
super(simpleName, fieldType, defaultFieldType, ignoreMalformed, coerce, ignoreZValue, orientation, indexSettings,
|
||||
multiFields, copyTo);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.elasticsearch.geometry.MultiPolygon;
|
|||
import org.elasticsearch.geometry.Point;
|
||||
import org.elasticsearch.geometry.Polygon;
|
||||
import org.elasticsearch.geometry.Rectangle;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ParseContext;
|
||||
import org.elasticsearch.xpack.spatial.common.ShapeUtils;
|
||||
|
||||
|
@ -27,7 +27,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ShapeIndexer implements AbstractGeometryFieldMapper.Indexer<Geometry, Geometry> {
|
||||
public class ShapeIndexer implements AbstractShapeGeometryFieldMapper.Indexer<Geometry, Geometry> {
|
||||
private final String name;
|
||||
|
||||
public ShapeIndexer(String name) {
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.elasticsearch.common.logging.DeprecationLogger;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.query.AbstractGeometryQueryBuilder;
|
||||
import org.elasticsearch.index.query.GeoShapeQueryBuilder;
|
||||
|
@ -139,7 +139,7 @@ public class ShapeQueryBuilder extends AbstractGeometryQueryBuilder<ShapeQueryBu
|
|||
+ "] but of type [" + fieldType.typeName() + "]");
|
||||
}
|
||||
|
||||
final AbstractSearchableGeometryFieldType ft = (AbstractSearchableGeometryFieldType) fieldType;
|
||||
final AbstractGeometryFieldType ft = (AbstractGeometryFieldType) fieldType;
|
||||
return new ConstantScoreQuery(ft.geometryQueryBuilder().process(shape, ft.name(), relation, context));
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.elasticsearch.geometry.Point;
|
|||
import org.elasticsearch.geometry.Polygon;
|
||||
import org.elasticsearch.geometry.Rectangle;
|
||||
import org.elasticsearch.geometry.ShapeType;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType.QueryProcessor;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
|
@ -34,7 +34,7 @@ import org.elasticsearch.xpack.spatial.index.mapper.PointFieldMapper;
|
|||
import org.elasticsearch.xpack.spatial.common.ShapeUtils;
|
||||
|
||||
|
||||
public class ShapeQueryPointProcessor implements AbstractSearchableGeometryFieldType.QueryProcessor {
|
||||
public class ShapeQueryPointProcessor implements QueryProcessor {
|
||||
|
||||
@Override
|
||||
public Query process(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context) {
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.elasticsearch.geometry.MultiPolygon;
|
|||
import org.elasticsearch.geometry.Point;
|
||||
import org.elasticsearch.geometry.Polygon;
|
||||
import org.elasticsearch.geometry.Rectangle;
|
||||
import org.elasticsearch.index.mapper.AbstractSearchableGeometryFieldType;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper.AbstractGeometryFieldType.QueryProcessor;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.QueryShardException;
|
||||
|
@ -34,7 +34,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
|
||||
public class ShapeQueryProcessor implements AbstractSearchableGeometryFieldType.QueryProcessor {
|
||||
public class ShapeQueryProcessor implements QueryProcessor {
|
||||
|
||||
@Override
|
||||
public Query process(Geometry shape, String fieldName, ShapeRelation relation, QueryShardContext context) {
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
|||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.DocumentMapperParser;
|
||||
import org.elasticsearch.index.mapper.Mapper;
|
||||
|
@ -361,7 +361,7 @@ public class GeoShapeWithDocValuesFieldMapperTests extends ESSingleNodeTestCase
|
|||
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
|
||||
String serialized = toXContentString((GeoShapeWithDocValuesFieldMapper) defaultMapper.mappers().getMapper("location"));
|
||||
assertTrue(serialized, serialized.contains("\"orientation\":\"" +
|
||||
AbstractGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
AbstractShapeGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
assertTrue(serialized, serialized.contains("\"doc_values\":true"));
|
||||
}
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ public class GeoShapeWithDocValuesFieldMapperTests extends ESSingleNodeTestCase
|
|||
DocumentMapper mapper = parser.parse("type1", new CompressedXContent(mapping));
|
||||
String serialized = toXContentString((GeoShapeWithDocValuesFieldMapper) mapper.mappers().getMapper("location"));
|
||||
assertTrue(serialized, serialized.contains("\"orientation\":\"" +
|
||||
AbstractGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
AbstractShapeGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
assertTrue(serialized, serialized.contains("\"doc_values\":" + docValues));
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
|||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.AbstractShapeGeometryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.DocumentMapperParser;
|
||||
import org.elasticsearch.index.mapper.Mapper;
|
||||
|
@ -273,7 +273,7 @@ public class ShapeFieldMapperTests extends CartesianFieldMapperTests {
|
|||
DocumentMapper defaultMapper = parser.parse("type1", new CompressedXContent(mapping));
|
||||
String serialized = toXContentString((ShapeFieldMapper) defaultMapper.mappers().getMapper("location"));
|
||||
assertTrue(serialized, serialized.contains("\"orientation\":\"" +
|
||||
AbstractGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
AbstractShapeGeometryFieldMapper.Defaults.ORIENTATION.value() + "\""));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue