Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 4 additions & 187 deletions docs/reference/mapping/types/geo-shape.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,61 +21,6 @@ type.
|=======================================================================
|Option |Description| Default

|`tree |deprecated[6.6, PrefixTrees no longer used] Name of the PrefixTree
implementation to be used: `geohash` for GeohashPrefixTree and `quadtree`
for QuadPrefixTree. Note: This parameter is only relevant for `term` and
`recursive` strategies.
| `quadtree`

|`precision` |deprecated[6.6, PrefixTrees no longer used] This parameter may
be used instead of `tree_levels` to set an appropriate value for the
`tree_levels` parameter. The value specifies the desired precision and
Elasticsearch will calculate the best tree_levels value to honor this
precision. The value should be a number followed by an optional distance
unit. Valid distance units include: `in`, `inch`, `yd`, `yard`, `mi`,
`miles`, `km`, `kilometers`, `m`,`meters`, `cm`,`centimeters`, `mm`,
`millimeters`. Note: This parameter is only relevant for `term` and
`recursive` strategies.
| `50m`

|`tree_levels` |deprecated[6.6, PrefixTrees no longer used] Maximum number
of layers to be used by the PrefixTree. This can be used to control the
precision of shape representations andtherefore how many terms are
indexed. Defaults to the default value of the chosen PrefixTree
implementation. Since this parameter requires a certain level of
understanding of the underlying implementation, users may use the
`precision` parameter instead. However, Elasticsearch only uses the
tree_levels parameter internally and this is what is returned via the
mapping API even if you use the precision parameter. Note: This parameter
is only relevant for `term` and `recursive` strategies.
| various

|`strategy` |deprecated[6.6, PrefixTrees no longer used] The strategy
parameter defines the approach for how to represent shapes at indexing
and search time. It also influences the capabilities available so it
is recommended to let Elasticsearch set this parameter automatically.
There are two strategies available: `recursive`, and `term`.
Recursive and Term strategies are deprecated and will be removed in a
future version. While they are still available, the Term strategy
supports point types only (the `points_only` parameter will be
automatically set to true) while Recursive strategy supports all
shape types. (IMPORTANT: see <<prefix-trees, Prefix trees>> for more
detailed information about these strategies)
| `recursive`

|`distance_error_pct` |deprecated[6.6, PrefixTrees no longer used] Used as a
hint to the PrefixTree about how precise it should be. Defaults to 0.025 (2.5%)
with 0.5 as the maximum supported value. PERFORMANCE NOTE: This value will
default to 0 if a `precision` or `tree_level` definition is explicitly defined.
This guarantees spatial precision at the level defined in the mapping. This can
lead to significant memory usage for high resolution shapes with low error
(e.g., large shapes at 1m with < 0.001 error). To improve indexing performance
(at the cost of query accuracy) explicitly define `tree_level` or `precision`
along with a reasonable `distance_error_pct`, noting that large shapes will have
greater false positives. Note: This parameter is only relevant for `term` and
`recursive` strategies.
| `0.025`

|`orientation` |Optionally define how to interpret vertex order for
polygons / multipolygons. This parameter defines one of two coordinate
system rules (Right-hand or Left-hand) each of which can be specified in three
Expand All @@ -88,15 +33,6 @@ sets vertex order for the coordinate list of a geo_shape field but can be
overridden in each individual GeoJSON or WKT document.
| `ccw`

|`points_only` |deprecated[6.6, PrefixTrees no longer used] Setting this option to
`true` (defaults to `false`) configures the `geo_shape` field type for point
shapes only (NOTE: Multi-Points are not yet supported). This optimizes index and
search performance for the `geohash` and `quadtree` when it is known that only points
will be indexed. At present geo_shape queries can not be executed on `geo_point`
field types. This option bridges the gap by improving point performance on a
`geo_shape` field so that `geo_shape` queries are optimal on a point only field.
| `false`

|`ignore_malformed` |If true, malformed GeoJSON or WKT shapes are ignored. If
false (default), malformed GeoJSON and WKT shapes throw an exception and reject the
entire document.
Expand All @@ -114,84 +50,13 @@ and reject the whole document.

[[geoshape-indexing-approach]]
[float]
==== Indexing approach
==== Indexing approach and Accuracy
GeoShape types are indexed by decomposing the shape into a triangular mesh and
indexing each triangle as a 7 dimension point in a BKD tree. This provides
near perfect spatial resolution (down to 1e-7 decimal degree precision) since all
spatial relations are computed using an encoded vector representation of the
original shape instead of a raster-grid representation as used by the
<<prefix-trees>> indexing approach. Performance of the tessellator primarily
depends on the number of vertices that define the polygon/multi-polygon. While
this is the default indexing technique prefix trees can still be used by setting
the `tree` or `strategy` parameters according to the appropriate
<<geo-shape-mapping-options>>. Note that these parameters are now deprecated
and will be removed in a future version.

[[prefix-trees]]
[float]
==== Prefix trees

deprecated[6.6, PrefixTrees no longer used] To efficiently represent shapes in
an inverted index, Shapes are converted into a series of hashes representing
grid squares (commonly referred to as "rasters") using implementations of a
PrefixTree. The tree notion comes from the fact that the PrefixTree uses multiple
grid layers, each with an increasing level of precision to represent the Earth.
This can be thought of as increasing the level of detail of a map or image at higher
zoom levels. Since this approach causes precision issues with indexed shape, it has
been deprecated in favor of a vector indexing approach that indexes the shapes as a
triangular mesh (see <<geoshape-indexing-approach>>).

Multiple PrefixTree implementations are provided:

* GeohashPrefixTree - Uses
http://en.wikipedia.org/wiki/Geohash[geohashes] for grid squares.
Geohashes are base32 encoded strings of the bits of the latitude and
longitude interleaved. So the longer the hash, the more precise it is.
Each character added to the geohash represents another tree level and
adds 5 bits of precision to the geohash. A geohash represents a
rectangular area and has 32 sub rectangles. The maximum number of levels
in Elasticsearch is 24; the default is 9.
* QuadPrefixTree - Uses a
http://en.wikipedia.org/wiki/Quadtree[quadtree] for grid squares.
Similar to geohash, quad trees interleave the bits of the latitude and
longitude the resulting hash is a bit set. A tree level in a quad tree
represents 2 bits in this bit set, one for each coordinate. The maximum
number of levels for the quad trees in Elasticsearch is 29; the default is 21.

[[spatial-strategy]]
[float]
===== Spatial strategies
deprecated[6.6, PrefixTrees no longer used] The indexing implementation
selected relies on a SpatialStrategy for choosing how to decompose the shapes
(either as grid squares or a tessellated triangular mesh). Each strategy
answers the following:

* What type of Shapes can be indexed?
* What types of Query Operations and Shapes can be used?
* Does it support more than one Shape per field?

The following Strategy implementations (with corresponding capabilities)
are provided:

[cols="<,<,<,<",options="header",]
|=======================================================================
|Strategy |Supported Shapes |Supported Queries |Multiple Shapes

|`recursive` |<<input-structure, All>> |`INTERSECTS`, `DISJOINT`, `WITHIN`, `CONTAINS` |Yes
|`term` |<<point, Points>> |`INTERSECTS` |Yes

|=======================================================================

[float]
===== Accuracy

`Recursive` and `Term` strategies do not provide 100% accuracy and depending on
how they are configured it may return some false positives for `INTERSECTS`,
`WITHIN` and `CONTAINS` queries, and some false negatives for `DISJOINT` queries.
To mitigate this, it is important to select an appropriate value for the tree_levels
parameter and to adjust expectations accordingly. For example, a point may be near
the border of a particular grid cell and may thus not match a query that only matches
the cell right next to it -- even though the shape is very close to the point.
original shape. Performance of the tessellator primarily depends on the number of
vertices that define the polygon/multi-polygon.

[float]
===== Example
Expand All @@ -215,27 +80,7 @@ PUT /example
// TESTSETUP

This mapping definition maps the location field to the geo_shape
type using the default vector implementation. It provides
approximately 1e-7 decimal degree precision.

[float]
===== Performance considerations with Prefix Trees

deprecated[6.6, PrefixTrees no longer used] With prefix trees,
Elasticsearch uses the paths in the tree as terms in the inverted index
and in queries. The higher the level (and thus the precision), the more
terms are generated. Of course, calculating the terms, keeping them in
memory, and storing them on disk all have a price. Especially with higher
tree levels, indices can become extremely large even with a modest amount
of data. Additionally, the size of the features also matters. Big, complex
polygons can take up a lot of space at higher tree levels. Which setting
is right depends on the use case. Generally one trades off accuracy against
index size and query performance.

The defaults in Elasticsearch for both implementations are a compromise
between index size and a reasonable level of precision of 50m at the
equator. This allows for indexing tens of millions of shapes without
overly bloating the resulting index too much relative to the input size.
type with approximately 1e-7 decimal degree spatial precision.

[[input-structure]]
[float]
Expand Down Expand Up @@ -624,34 +469,6 @@ POST /example/doc
--------------------------------------------------
// CONSOLE

[float]
===== Circle

Elasticsearch supports a `circle` type, which consists of a center
point with a radius. Note that this circle representation can only
be indexed when using the `recursive` Prefix Tree strategy. For
the default <<geoshape-indexing-approach>> circles should be approximated using
a `POLYGON`.

[source,js]
--------------------------------------------------
POST /example/doc
{
"location" : {
"type" : "circle",
"coordinates" : [101.0, 1.0],
"radius" : "100m"
}
}
--------------------------------------------------
// CONSOLE
// TEST[skip:not supported in default]

Note: The inner `radius` field is required. If not specified, then
the units of the `radius` will default to `METERS`.

*NOTE:* Neither GeoJSON or WKT support a point-radius circle type.

[float]
==== Sorting and Retrieving index Shapes

Expand Down
20 changes: 3 additions & 17 deletions docs/reference/migration/migrate_7_0/mappings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,7 @@ An error will now be thrown when unknown configuration options are provided
to similarities. Such unknown parameters were ignored before.

[float]
==== Changed default `geo_shape` indexing strategy
==== prohibit use of `geo_shape` prefix tree parameters for new indexes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/prohibit/Prohibit/?


`geo_shape` types now default to using a vector indexing approach based on Lucene's new
`LatLonShape` field type. This indexes shapes as a triangular mesh instead of decomposing
them into individual grid cells. To index using legacy prefix trees the `tree` parameter
must be explicitly set to one of `quadtree` or `geohash`. Note that these strategies are
now deprecated and will be removed in a future version.

IMPORTANT NOTE: If using timed index creation from templates, the `geo_shape` mapping
should also be changed in the template to explicitly define `tree` to one of `geohash`
or `quadtree`. This will ensure compatibility with previously created indexes.

[float]
==== deprecated `geo_shape` parameters

The following type parameters are deprecated for the `geo_shape` field type: `tree`,
`precision`, `tree_levels`, `distance_error_pct`, `points_only`, and `strategy`. They
will be removed in a future version.
The following type parameters are now prohibited for the `geo_shape` field type: `tree`,
`precision`, `tree_levels`, `distance_error_pct`, `points_only`, and `strategy`.
13 changes: 1 addition & 12 deletions docs/reference/query-dsl/geo-shape-query.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ Filter documents indexed using the `geo_shape` type.

Requires the <<geo-shape,`geo_shape` Mapping>>.

The `geo_shape` query uses the same grid square representation as the
`geo_shape` mapping to find documents that have a shape that intersects
with the query shape. It will also use the same Prefix Tree configuration
as defined for the field mapping.

The query supports two ways of defining the query shape, either by
The `geo_shape` query supports two ways of defining the query shape, either by
providing a whole shape definition, or by referencing the name of a shape
pre-indexed in another index. Both formats are defined below with
examples.
Expand Down Expand Up @@ -145,9 +140,6 @@ GET /example/_search

==== Spatial Relations

The <<spatial-strategy, geo_shape strategy>> mapping parameter determines
which spatial relation operators may be used at search time.

The following is a complete list of spatial relation operators available:

* `INTERSECTS` - (default) Return all documents whose `geo_shape` field
Expand All @@ -156,9 +148,6 @@ intersects the query geometry.
has nothing in common with the query geometry.
* `WITHIN` - Return all documents whose `geo_shape` field
is within the query geometry.
* `CONTAINS` - Return all documents whose `geo_shape` field
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's maybe keep it in the docs since the plan is to have it back by 7.0?

contains the query geometry. Note: this is only supported using the
`recursive` Prefix Tree Strategy deprecated[6.6]

[float]
==== Ignore Unmapped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext
Map.Entry<String, Object> entry = iterator.next();
String fieldName = entry.getKey();
Object fieldNode = entry.getValue();
if (DeprecatedParameters.parse(name, fieldName, fieldNode, deprecatedParameters)) {
if (DeprecatedParameters.parse(parserContext, name, fieldName, fieldNode, deprecatedParameters)) {
parsedDeprecatedParams = true;
iterator.remove();
} else if (Names.ORIENTATION.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.mapper.Mapper.TypeParser.ParserContext;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Shape;
import org.locationtech.spatial4j.shape.jts.JtsGeometry;
Expand Down Expand Up @@ -144,24 +145,25 @@ public void setDistanceErrorPct(double distanceErrorPct) {
this.distanceErrorPct = distanceErrorPct;
}

public static boolean parse(String name, String fieldName, Object fieldNode, DeprecatedParameters deprecatedParameters) {
public static boolean parse(ParserContext parserContext, String name, String fieldName, Object fieldNode,
DeprecatedParameters deprecatedParameters) {
if (Names.STRATEGY.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
checkPrefixTreeSupport(fieldName);
checkPrefixTreeSupport(parserContext, fieldName);
deprecatedParameters.setSpatialStrategy(SpatialStrategy.fromString(fieldNode.toString()));
} else if (Names.TREE.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
checkPrefixTreeSupport(fieldName);
checkPrefixTreeSupport(parserContext, fieldName);
deprecatedParameters.setTree(fieldNode.toString());
} else if (Names.TREE_LEVELS.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
checkPrefixTreeSupport(fieldName);
checkPrefixTreeSupport(parserContext, fieldName);
deprecatedParameters.setTreeLevels(Integer.parseInt(fieldNode.toString()));
} else if (Names.PRECISION.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
checkPrefixTreeSupport(fieldName);
checkPrefixTreeSupport(parserContext, fieldName);
deprecatedParameters.setPrecision(fieldNode.toString());
} else if (Names.DISTANCE_ERROR_PCT.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
checkPrefixTreeSupport(fieldName);
checkPrefixTreeSupport(parserContext, fieldName);
deprecatedParameters.setDistanceErrorPct(Double.parseDouble(fieldNode.toString()));
} else if (Names.POINTS_ONLY.match(fieldName, LoggingDeprecationHandler.INSTANCE)) {
checkPrefixTreeSupport(fieldName);
checkPrefixTreeSupport(parserContext, fieldName);
deprecatedParameters.setPointsOnly(
XContentMapValues.nodeBooleanValue(fieldNode, name + "." + DeprecatedParameters.Names.POINTS_ONLY));
} else {
Expand All @@ -170,8 +172,9 @@ public static boolean parse(String name, String fieldName, Object fieldNode, Dep
return true;
}

private static void checkPrefixTreeSupport(String fieldName) {
if (ShapesAvailability.JTS_AVAILABLE == false || ShapesAvailability.SPATIAL4J_AVAILABLE == false) {
private static void checkPrefixTreeSupport(ParserContext parserContext, String fieldName) {
if (parserContext.indexVersionCreated().onOrAfter(Version.V_7_0_0)
|| ShapesAvailability.JTS_AVAILABLE == false || ShapesAvailability.SPATIAL4J_AVAILABLE == false) {
throw new ElasticsearchParseException("Field parameter [{}] is not supported for [{}] field type",
fieldName, CONTENT_TYPE);
}
Expand Down Expand Up @@ -552,7 +555,7 @@ protected void doXContentBody(XContentBuilder builder, boolean includeDefaults,
DistanceUnit.METERS.toString(50));
}

if (indexCreatedVersion.onOrAfter(Version.V_7_0_0)) {
if (indexCreatedVersion.onOrAfter(Version.V_6_6_0)) {
builder.field(DeprecatedParameters.Names.STRATEGY.getPreferredName(), fieldType().strategy().getStrategyName());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public ExternalMapper build(BuilderContext context) {
BinaryFieldMapper binMapper = binBuilder.build(context);
BooleanFieldMapper boolMapper = boolBuilder.build(context);
GeoPointFieldMapper pointMapper = latLonPointBuilder.build(context);
BaseGeoShapeFieldMapper shapeMapper = (context.indexCreatedVersion().before(Version.V_7_0_0))
BaseGeoShapeFieldMapper shapeMapper = (context.indexCreatedVersion().before(Version.V_6_6_0))
? legacyShapeBuilder.build(context)
: shapeBuilder.build(context);
FieldMapper stringMapper = (FieldMapper)stringBuilder.build(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,7 @@ public Function<String, Predicate<String>> getFieldFilter() {
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"area_visible\": {\n" +
" \"type\": \"geo_shape\", \n" +
" \"tree\": \"quadtree\",\n" +
" \"precision\": \"1m\"\n" +
" \"type\": \"geo_shape\"\n" +
" }\n" +
" }\n" +
" },\n" +
Expand Down
Loading