Currently multi-point queries are not supported when indexing your data using BKD-backed geoshape strategy. This commit removes this limitation.
This commit is contained in:
parent
4bc7545e43
commit
107f00a4ec
|
@ -134,16 +134,10 @@ and will be removed in a future version.
|
|||
|
||||
*IMPORTANT NOTES*
|
||||
|
||||
The following features are not yet supported with the new indexing approach:
|
||||
`CONTAINS` relation query - when using the new default vector indexing strategy, `geo_shape`
|
||||
queries with `relation` defined as `contains` are supported for indices created with
|
||||
ElasticSearch 7.5.0 or higher.
|
||||
|
||||
* `geo_shape` query with `MultiPoint` geometry types - Elasticsearch currently prevents searching
|
||||
geo_shape fields with a MultiPoint geometry type to avoid a brute force linear search
|
||||
over each individual point. For now, if this is absolutely needed, this can be achieved
|
||||
using a `bool` query with each individual point.
|
||||
|
||||
* `CONTAINS` relation query - when using the new default vector indexing strategy, `geo_shape`
|
||||
queries with `relation` defined as `contains` are supported for indices created with
|
||||
ElasticSearch 7.5.0 or higher.
|
||||
|
||||
[[prefix-trees]]
|
||||
[float]
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.apache.lucene.search.BooleanQuery;
|
|||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.geo.GeoShapeType;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.geometry.Circle;
|
||||
import org.elasticsearch.geometry.Geometry;
|
||||
|
@ -106,13 +105,7 @@ public class VectorGeoShapeQueryProcessor implements AbstractGeometryFieldMapper
|
|||
occur = BooleanClause.Occur.SHOULD;
|
||||
}
|
||||
for (Geometry shape : collection) {
|
||||
if (shape instanceof MultiPoint) {
|
||||
// Flatten multi-points
|
||||
// We do not support multi-point queries?
|
||||
visit(bqb, (GeometryCollection<?>) shape);
|
||||
} else {
|
||||
bqb.add(shape.visit(this), occur);
|
||||
}
|
||||
bqb.add(shape.visit(this), occur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,8 +132,11 @@ public class VectorGeoShapeQueryProcessor implements AbstractGeometryFieldMapper
|
|||
|
||||
@Override
|
||||
public Query visit(MultiPoint multiPoint) {
|
||||
throw new QueryShardException(context, "Field [" + fieldName + "] does not support " + GeoShapeType.MULTIPOINT +
|
||||
" queries");
|
||||
double[][] points = new double[multiPoint.size()][2];
|
||||
for (int i = 0; i < multiPoint.size(); i++) {
|
||||
points[i] = new double[] {multiPoint.get(i).getLat(), multiPoint.get(i).getLon()};
|
||||
}
|
||||
return LatLonShape.newPointQuery(fieldName, relation.getLuceneRelation(), points);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -161,8 +157,8 @@ public class VectorGeoShapeQueryProcessor implements AbstractGeometryFieldMapper
|
|||
// intersects is more efficient.
|
||||
luceneRelation = ShapeField.QueryRelation.INTERSECTS;
|
||||
}
|
||||
return LatLonShape.newBoxQuery(fieldName, luceneRelation,
|
||||
point.getY(), point.getY(), point.getX(), point.getX());
|
||||
return LatLonShape.newPointQuery(fieldName, luceneRelation,
|
||||
new double[] {point.getY(), point.getX()});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -84,9 +84,8 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
|
|||
}
|
||||
|
||||
protected GeoShapeQueryBuilder doCreateTestQueryBuilder(boolean indexedShape) {
|
||||
// LatLonShape does not support MultiPoint queries
|
||||
RandomShapeGenerator.ShapeType shapeType =
|
||||
randomFrom(ShapeType.POINT, ShapeType.LINESTRING, ShapeType.MULTILINESTRING, ShapeType.POLYGON);
|
||||
randomFrom(ShapeType.POINT, ShapeType.MULTIPOINT, ShapeType.LINESTRING, ShapeType.MULTILINESTRING, ShapeType.POLYGON);
|
||||
ShapeBuilder<?, ?, ?> shape = RandomShapeGenerator.createShapeWithin(random(), null, shapeType);
|
||||
GeoShapeQueryBuilder builder;
|
||||
clearShapeFields();
|
||||
|
@ -111,11 +110,20 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
|
|||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
if (shapeType == ShapeType.LINESTRING || shapeType == ShapeType.MULTILINESTRING) {
|
||||
builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.INTERSECTS));
|
||||
QueryShardContext context = createShardContext();
|
||||
if (context.indexVersionCreated().onOrAfter(Version.V_7_5_0)) { // CONTAINS is only supported from version 7.5
|
||||
if (shapeType == ShapeType.LINESTRING || shapeType == ShapeType.MULTILINESTRING) {
|
||||
builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.INTERSECTS, ShapeRelation.CONTAINS));
|
||||
} else {
|
||||
builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.INTERSECTS,
|
||||
ShapeRelation.WITHIN, ShapeRelation.CONTAINS));
|
||||
}
|
||||
} else {
|
||||
// LatLonShape does not support CONTAINS:
|
||||
builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.INTERSECTS, ShapeRelation.WITHIN));
|
||||
if (shapeType == ShapeType.LINESTRING || shapeType == ShapeType.MULTILINESTRING) {
|
||||
builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.INTERSECTS));
|
||||
} else {
|
||||
builder.relation(randomFrom(ShapeRelation.DISJOINT, ShapeRelation.INTERSECTS, ShapeRelation.WITHIN));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -206,23 +206,8 @@ public class GeoShapeQueryTests extends GeoQueryTests {
|
|||
}
|
||||
|
||||
public void testRandomGeoCollectionQuery() throws Exception {
|
||||
boolean usePrefixTrees = randomBoolean();
|
||||
// Create a random geometry collection to index.
|
||||
GeometryCollectionBuilder gcb;
|
||||
if (usePrefixTrees) {
|
||||
gcb = RandomShapeGenerator.createGeometryCollection(random());
|
||||
} else {
|
||||
// vector strategy does not yet support multipoint queries
|
||||
gcb = new GeometryCollectionBuilder();
|
||||
int numShapes = RandomNumbers.randomIntBetween(random(), 1, 4);
|
||||
for (int i = 0; i < numShapes; ++i) {
|
||||
ShapeBuilder shape;
|
||||
do {
|
||||
shape = RandomShapeGenerator.createShape(random());
|
||||
} while (shape instanceof MultiPointBuilder);
|
||||
gcb.shape(shape);
|
||||
}
|
||||
}
|
||||
GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random());
|
||||
org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon();
|
||||
|
||||
assumeTrue("Skipping the check for the polygon with a degenerated dimension",
|
||||
|
@ -234,10 +219,9 @@ public class GeoShapeQueryTests extends GeoQueryTests {
|
|||
}
|
||||
gcb.shape(new PolygonBuilder(cb));
|
||||
|
||||
logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(),
|
||||
usePrefixTrees ? "geohash" : "quadtree");
|
||||
logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes());
|
||||
|
||||
XContentBuilder mapping = createPrefixTreeMapping(usePrefixTrees ? "geohash" : "quadtree");
|
||||
XContentBuilder mapping = createRandomMapping();
|
||||
Settings settings = Settings.builder().put("index.number_of_shards", 1).build();
|
||||
client().admin().indices().prepareCreate("test").addMapping("_doc",mapping).setSettings(settings).get();
|
||||
ensureGreen();
|
||||
|
@ -321,8 +305,7 @@ public class GeoShapeQueryTests extends GeoQueryTests {
|
|||
}
|
||||
|
||||
public void testGeometryCollectionRelations() throws Exception {
|
||||
XContentBuilder mapping = createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH);
|
||||
|
||||
XContentBuilder mapping = createDefaultMapping();
|
||||
createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping);
|
||||
|
||||
EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10));
|
||||
|
@ -441,13 +424,13 @@ public class GeoShapeQueryTests extends GeoQueryTests {
|
|||
|
||||
public void testReusableBuilder() throws IOException {
|
||||
PolygonBuilder polygon = new PolygonBuilder(new CoordinatesBuilder()
|
||||
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close())
|
||||
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5)
|
||||
.coordinate(175, 5).close()));
|
||||
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close())
|
||||
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5)
|
||||
.coordinate(175, 5).close()));
|
||||
assertUnmodified(polygon);
|
||||
|
||||
LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder()
|
||||
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
|
||||
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
|
||||
assertUnmodified(linestring);
|
||||
}
|
||||
|
||||
|
@ -534,13 +517,9 @@ public class GeoShapeQueryTests extends GeoQueryTests {
|
|||
GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random());
|
||||
logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes());
|
||||
|
||||
if (randomBoolean()) {
|
||||
client().admin().indices().prepareCreate("test").addMapping("type", "geo", "type=geo_shape")
|
||||
.execute().actionGet();
|
||||
} else {
|
||||
client().admin().indices().prepareCreate("test").addMapping("type", "geo", "type=geo_shape,tree=quadtree")
|
||||
.execute().actionGet();
|
||||
}
|
||||
XContentBuilder builder = createRandomMapping();
|
||||
client().admin().indices().prepareCreate("test").addMapping("type", builder)
|
||||
.execute().actionGet();
|
||||
|
||||
XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject();
|
||||
client().prepareIndex("test", "type", "1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get();
|
||||
|
@ -696,13 +675,9 @@ public class GeoShapeQueryTests extends GeoQueryTests {
|
|||
|
||||
logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes());
|
||||
|
||||
if (randomBoolean()) {
|
||||
client().admin().indices().prepareCreate("test")
|
||||
.addMapping("type", "geo", "type=geo_shape").get();
|
||||
} else {
|
||||
client().admin().indices().prepareCreate("test")
|
||||
.addMapping("type", "geo", "type=geo_shape,tree=quadtree").get();
|
||||
}
|
||||
XContentBuilder builder = createRandomMapping();
|
||||
client().admin().indices().prepareCreate("test")
|
||||
.addMapping("type", builder).get();
|
||||
|
||||
XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject();
|
||||
client().prepareIndex("test", "type", "1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get();
|
||||
|
|
Loading…
Reference in New Issue