From a5f09fbfbe21fee1960467da4ce6d124a1bc501f Mon Sep 17 00:00:00 2001 From: djptek Date: Fri, 15 Nov 2019 19:05:23 +0100 Subject: [PATCH 01/18] WIP subclassing GeoShapeQueryTests.java --- .../geo/GeoShapeGeoPointQueryTests.java | 666 ++++++++++++++++++ .../geo/GeoShapeGeoShapeQueryTests.java | 666 ++++++++++++++++++ .../search/geo/GeoShapeQueryTests.java | 634 +---------------- 3 files changed, 1335 insertions(+), 631 deletions(-) create mode 100644 server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java create mode 100644 server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java new file mode 100644 index 0000000000000..4995e574aceb0 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java @@ -0,0 +1,666 @@ +package org.elasticsearch.search.geo; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.SpatialStrategy; +import org.elasticsearch.common.geo.builders.*; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.query.ExistsQueryBuilder; +import org.elasticsearch.index.query.GeoShapeQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.geo.RandomShapeGenerator; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.spatial4j.shape.Rectangle; + +import java.io.IOException; +import java.util.Locale; + +import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.test.geo.RandomShapeGenerator.*; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.Matchers.*; + +public class GeoShapeGeoPointQueryTests extends GeoShapeQueryTests { + + public void testIndexPointsFilterRectangle() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() + .field("name", "Document 2") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-45).value(-50).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("location", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testEdgeCases() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .endObject().endObject().endObject().endObject(); + String mapping = Strings.toString(xcb); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() + .field("name", "Blakely Island") + .startObject("location") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-122.83).value(48.57).endArray() + .startArray().value(-122.77).value(48.56).endArray() + .startArray().value(-122.79).value(48.53).endArray() + .startArray().value(-122.83).value(48.57).endArray() // close the polygon + .endArray().endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder query = new EnvelopeBuilder(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54)); + + // This search would fail if both geoshape indexing and geoshape filtering + // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", query)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); + } + + public void testIndexedShapeReference() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + createIndex("shapes"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("location", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testIndexedShapeReferenceSourceDisabled() throws Exception { + XContentBuilder mapping = createMapping(); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); + createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); + assertThat(e.getMessage(), containsString("source disabled")); + } + + 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())); + assertUnmodified(polygon); + + LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder() + .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()); + assertUnmodified(linestring); + } + + private void assertUnmodified(ShapeBuilder builder) throws IOException { + String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); + builder.buildS4J(); + String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); + assertThat(before, equalTo(after)); + } + + public void testShapeFetchingPath() throws Exception { + createIndex("shapes"); + client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); + + String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; + + client().prepareIndex("shapes").setId("1") + .setSource( + String.format( + Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location + ), XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().startObject("location") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-20).value(-20).endArray() + .startArray().value(20).value(-20).endArray() + .startArray().value(20).value(20).endArray() + .startArray().value(-20).value(20).endArray() + .startArray().value(-20).value(-20).endArray() + .endArray().endArray() + .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("location"); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + + // now test the query variant + GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testQueryRandomGeoCollection() throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + if (randomBoolean()) { + client().admin().indices().prepareCreate("test") + .addMapping("type", "location", "type=geo_shape").get(); + } else { + client().admin().indices().prepareCreate("test") + .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assumeTrue("Skipping the check for the polygon with a degenerated dimension until " + +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + assertHitCount(result, 1); + } + + 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); + } + } + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + + assumeTrue("Skipping the check for the polygon with a degenerated dimension", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), + usePrefixTrees ? "default" : "quadtree"); + + if (usePrefixTrees == false) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // Create a random geometry collection to query + GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); + queryCollection.shape(new PolygonBuilder(cb)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), + result.getHits().getTotalHits().value > 0); + } + + /** tests querying a random geometry collection with a point */ + public void testPointQuery() throws Exception { + // Create a random geometry collection to index. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; + PointBuilder pb = new PointBuilder(pt[0], pt[1]); + gcb.shape(pb); + if (randomBoolean()) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testContainsShapeQuery() throws Exception { + // Create a random geometry collection. + Rectangle mbr = xRandomRectangle(random(), xRandomPoint(random()), true); + GeometryCollectionBuilder gcb = createGeometryCollectionWithin(random(), mbr); + + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree" ) + .get(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // index the mbr of the collection + EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), + new Coordinate(mbr.getMaxX(), mbr.getMinY())); + docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) + .relation(ShapeRelation.CONTAINS); + SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(response); + + assertThat(response.getHits().getTotalHits().value, greaterThan(0L)); + } + + public void testExistsQuery() throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + if (randomBoolean()) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); + SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testShapeFilterWithDefinedGeoCollection() throws Exception { + createIndex("shapes"); + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .get(); + + XContentBuilder docSource = jsonBuilder().startObject().startObject("location") + .field("type", "geometrycollection") + .startArray("geometries") + .startObject() + .field("type", "point") + .startArray("coordinates") + .value(100.0).value(0.0) + .endArray() + .endObject() + .startObject() + .field("type", "linestring") + .startArray("coordinates") + .startArray() + .value(101.0).value(0.0) + .endArray() + .startArray() + .value(102.0).value(1.0) + .endArray() + .endArray() + .endObject() + .endArray() + .endObject().endObject(); + client().prepareIndex("test").setId("1") + .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( + "location", + new GeometryCollectionBuilder() + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) + .coordinate(103.0, 3.0).coordinate(103.0, -1.0) + .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery( + "location", + new GeometryCollectionBuilder().polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() + .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) + .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + // no shape + filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + } + + public void testPointsOnly() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .field("tree_levels", "6") + .field("distance_error_pct", "0.01") + .field("points_only", true) + .endObject().endObject() + .endObject().endObject()); + + client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random()); + try { + client().prepareIndex("geo_points_only").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + } catch (MapperParsingException e) { + // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown + assertThat(e.getCause().getMessage(), containsString("is configured for points only")); + return; + } + + // test that point was inserted + SearchResponse response = client().prepareSearch("geo_points_only") + .setQuery(geoIntersectionQuery("location", shape)) + .get(); + + assertEquals(1, response.getHits().getTotalHits().value); + } + + public void testPointsOnlyExplicit() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .field("tree_levels", "6") + .field("distance_error_pct", "0.01") + .field("points_only", true) + .endObject().endObject() + .endObject().endObject()); + + client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + // MULTIPOINT + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); + client().prepareIndex("geo_points_only").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + // POINT + shape = RandomShapeGenerator.createShape(random(), ShapeType.POINT); + client().prepareIndex("geo_points_only").setId("2") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + // test that point was inserted + SearchResponse response = client().prepareSearch("geo_points_only") + .setQuery(matchAllQuery()) + .get(); + + assertEquals(2, response.getHits().getTotalHits().value); + } + + public void testFieldAlias() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() + .endObject() + .endObject(); + + createIndex("test", Settings.EMPTY, "type", mapping); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("alias", shape)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } + + // Test for issue #34418 + public void testEnvelopeSpanningDateline() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("doc") + .startObject("properties") + .startObject("geo").field("type", "geo_shape").endObject() + .endObject() + .endObject() + .endObject(); + + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + + String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( + () -> QueryBuilders.geoShapeQuery( + "geo", + new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) + ).relation(ShapeRelation.WITHIN), + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .startObject("shape") + .field("type", "envelope") + .startArray("coordinates") + .startArray().value(-21).value(44).endArray() + .startArray().value(-39).value(9).endArray() + .endArray() + .endObject() + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + }, + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .field("shape", "BBOX (-21, -39, 44, 9)") + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + } + ); + + SearchResponse response = client().prepareSearch("test") + .setQuery(querySupplier.get()) + .get(); + assertEquals(2, response.getHits().getTotalHits().value); + assertNotEquals("1", response.getHits().getAt(0).getId()); + assertNotEquals("1", response.getHits().getAt(1).getId()); + } +} diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java new file mode 100644 index 0000000000000..62cad410f09be --- /dev/null +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java @@ -0,0 +1,666 @@ +package org.elasticsearch.search.geo; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.SpatialStrategy; +import org.elasticsearch.common.geo.builders.*; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.query.ExistsQueryBuilder; +import org.elasticsearch.index.query.GeoShapeQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.geo.RandomShapeGenerator; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.spatial4j.shape.Rectangle; + +import java.io.IOException; +import java.util.Locale; + +import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.test.geo.RandomShapeGenerator.*; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.Matchers.*; + +public class GeoShapeGeoShapeQueryTests extends GeoShapeQueryTests { + + public void testIndexPointsFilterRectangle() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() + .field("name", "Document 2") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-45).value(-50).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("location", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testEdgeCases() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .endObject().endObject().endObject().endObject(); + String mapping = Strings.toString(xcb); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() + .field("name", "Blakely Island") + .startObject("location") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-122.83).value(48.57).endArray() + .startArray().value(-122.77).value(48.56).endArray() + .startArray().value(-122.79).value(48.53).endArray() + .startArray().value(-122.83).value(48.57).endArray() // close the polygon + .endArray().endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder query = new EnvelopeBuilder(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54)); + + // This search would fail if both geoshape indexing and geoshape filtering + // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", query)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); + } + + public void testIndexedShapeReference() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + createIndex("shapes"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("location", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testIndexedShapeReferenceSourceDisabled() throws Exception { + XContentBuilder mapping = createMapping(); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); + createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); + assertThat(e.getMessage(), containsString("source disabled")); + } + + 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())); + assertUnmodified(polygon); + + LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder() + .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()); + assertUnmodified(linestring); + } + + private void assertUnmodified(ShapeBuilder builder) throws IOException { + String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); + builder.buildS4J(); + String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); + assertThat(before, equalTo(after)); + } + + public void testShapeFetchingPath() throws Exception { + createIndex("shapes"); + client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); + + String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; + + client().prepareIndex("shapes").setId("1") + .setSource( + String.format( + Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location + ), XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().startObject("location") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-20).value(-20).endArray() + .startArray().value(20).value(-20).endArray() + .startArray().value(20).value(20).endArray() + .startArray().value(-20).value(20).endArray() + .startArray().value(-20).value(-20).endArray() + .endArray().endArray() + .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("location"); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + + // now test the query variant + GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testQueryRandomGeoCollection() throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + if (randomBoolean()) { + client().admin().indices().prepareCreate("test") + .addMapping("type", "location", "type=geo_shape").get(); + } else { + client().admin().indices().prepareCreate("test") + .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assumeTrue("Skipping the check for the polygon with a degenerated dimension until " + +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + assertHitCount(result, 1); + } + + 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); + } + } + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + + assumeTrue("Skipping the check for the polygon with a degenerated dimension", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), + usePrefixTrees ? "default" : "quadtree"); + + if (usePrefixTrees == false) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // Create a random geometry collection to query + GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); + queryCollection.shape(new PolygonBuilder(cb)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), + result.getHits().getTotalHits().value > 0); + } + + /** tests querying a random geometry collection with a point */ + public void testPointQuery() throws Exception { + // Create a random geometry collection to index. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; + PointBuilder pb = new PointBuilder(pt[0], pt[1]); + gcb.shape(pb); + if (randomBoolean()) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testContainsShapeQuery() throws Exception { + // Create a random geometry collection. + Rectangle mbr = xRandomRectangle(random(), xRandomPoint(random()), true); + GeometryCollectionBuilder gcb = createGeometryCollectionWithin(random(), mbr); + + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree" ) + .get(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // index the mbr of the collection + EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), + new Coordinate(mbr.getMaxX(), mbr.getMinY())); + docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) + .relation(ShapeRelation.CONTAINS); + SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(response); + + assertThat(response.getHits().getTotalHits().value, greaterThan(0L)); + } + + public void testExistsQuery() throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + if (randomBoolean()) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); + SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testShapeFilterWithDefinedGeoCollection() throws Exception { + createIndex("shapes"); + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .get(); + + XContentBuilder docSource = jsonBuilder().startObject().startObject("location") + .field("type", "geometrycollection") + .startArray("geometries") + .startObject() + .field("type", "point") + .startArray("coordinates") + .value(100.0).value(0.0) + .endArray() + .endObject() + .startObject() + .field("type", "linestring") + .startArray("coordinates") + .startArray() + .value(101.0).value(0.0) + .endArray() + .startArray() + .value(102.0).value(1.0) + .endArray() + .endArray() + .endObject() + .endArray() + .endObject().endObject(); + client().prepareIndex("test").setId("1") + .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( + "location", + new GeometryCollectionBuilder() + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) + .coordinate(103.0, 3.0).coordinate(103.0, -1.0) + .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery( + "location", + new GeometryCollectionBuilder().polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() + .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) + .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + // no shape + filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + } + + public void testPointsOnly() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .field("tree_levels", "6") + .field("distance_error_pct", "0.01") + .field("points_only", true) + .endObject().endObject() + .endObject().endObject()); + + client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random()); + try { + client().prepareIndex("geo_points_only").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + } catch (MapperParsingException e) { + // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown + assertThat(e.getCause().getMessage(), containsString("is configured for points only")); + return; + } + + // test that point was inserted + SearchResponse response = client().prepareSearch("geo_points_only") + .setQuery(geoIntersectionQuery("location", shape)) + .get(); + + assertEquals(1, response.getHits().getTotalHits().value); + } + + public void testPointsOnlyExplicit() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .field("tree_levels", "6") + .field("distance_error_pct", "0.01") + .field("points_only", true) + .endObject().endObject() + .endObject().endObject()); + + client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + // MULTIPOINT + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); + client().prepareIndex("geo_points_only").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + // POINT + shape = RandomShapeGenerator.createShape(random(), ShapeType.POINT); + client().prepareIndex("geo_points_only").setId("2") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + // test that point was inserted + SearchResponse response = client().prepareSearch("geo_points_only") + .setQuery(matchAllQuery()) + .get(); + + assertEquals(2, response.getHits().getTotalHits().value); + } + + public void testFieldAlias() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() + .endObject() + .endObject(); + + createIndex("test", Settings.EMPTY, "type", mapping); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("alias", shape)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } + + // Test for issue #34418 + public void testEnvelopeSpanningDateline() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("doc") + .startObject("properties") + .startObject("geo").field("type", "geo_shape").endObject() + .endObject() + .endObject() + .endObject(); + + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + + String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( + () -> QueryBuilders.geoShapeQuery( + "geo", + new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) + ).relation(ShapeRelation.WITHIN), + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .startObject("shape") + .field("type", "envelope") + .startArray("coordinates") + .startArray().value(-21).value(44).endArray() + .startArray().value(-39).value(9).endArray() + .endArray() + .endObject() + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + }, + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .field("shape", "BBOX (-21, -39, 44, 9)") + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + } + ); + + SearchResponse response = client().prepareSearch("test") + .setQuery(querySupplier.get()) + .get(); + assertEquals(2, response.getHits().getTotalHits().value); + assertNotEquals("1", response.getHits().getAt(0).getId()); + assertNotEquals("1", response.getHits().getAt(1).getId()); + } +} diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 021fd47350789..5534d8c4c5403 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -70,13 +70,13 @@ import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.nullValue; -public class GeoShapeQueryTests extends ESSingleNodeTestCase { - private static final String[] PREFIX_TREES = new String[] { +public abstract class GeoShapeQueryTests extends ESSingleNodeTestCase { + protected static final String[] PREFIX_TREES = new String[] { LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH, LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE }; - private XContentBuilder createMapping() throws Exception { + protected XContentBuilder createMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") .startObject("properties").startObject("location") .field("type", "geo_shape"); @@ -99,632 +99,4 @@ public void testNullShape() throws Exception { GetResponse result = client().prepareGet("test", "aNullshape").get(); assertThat(result.getField("location"), nullValue()); } - - public void testIndexPointsFilterRectangle() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() - .field("name", "Document 2") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-45).value(-50).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", shape)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", shape)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - public void testEdgeCases() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .endObject().endObject().endObject().endObject(); - String mapping = Strings.toString(xcb); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() - .field("name", "Blakely Island") - .startObject("location") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-122.83).value(48.57).endArray() - .startArray().value(-122.77).value(48.56).endArray() - .startArray().value(-122.79).value(48.53).endArray() - .startArray().value(-122.83).value(48.57).endArray() // close the polygon - .endArray().endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - EnvelopeBuilder query = new EnvelopeBuilder(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54)); - - // This search would fail if both geoshape indexing and geoshape filtering - // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", query)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); - } - - public void testIndexedShapeReference() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - createIndex("shapes"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - public void testIndexedShapeReferenceSourceDisabled() throws Exception { - XContentBuilder mapping = createMapping(); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); - createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); - assertThat(e.getMessage(), containsString("source disabled")); - } - - 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())); - assertUnmodified(polygon); - - LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder() - .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()); - assertUnmodified(linestring); - } - - private void assertUnmodified(ShapeBuilder builder) throws IOException { - String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - builder.buildS4J(); - String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - assertThat(before, equalTo(after)); - } - - public void testShapeFetchingPath() throws Exception { - createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); - - String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; - - client().prepareIndex("shapes").setId("1") - .setSource( - String.format( - Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location - ), XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().startObject("location") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-20).value(-20).endArray() - .startArray().value(20).value(-20).endArray() - .startArray().value(20).value(20).endArray() - .startArray().value(-20).value(20).endArray() - .startArray().value(-20).value(-20).endArray() - .endArray().endArray() - .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("location"); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - - // now test the query variant - GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testQueryRandomGeoCollection() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - if (randomBoolean()) { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape").get(); - } else { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assumeTrue("Skipping the check for the polygon with a degenerated dimension until " - +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - assertHitCount(result, 1); - } - - 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); - } - } - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - - assumeTrue("Skipping the check for the polygon with a degenerated dimension", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), - usePrefixTrees ? "default" : "quadtree"); - - if (usePrefixTrees == false) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // Create a random geometry collection to query - GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); - queryCollection.shape(new PolygonBuilder(cb)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), - result.getHits().getTotalHits().value > 0); - } - - /** tests querying a random geometry collection with a point */ - public void testPointQuery() throws Exception { - // Create a random geometry collection to index. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; - PointBuilder pb = new PointBuilder(pt[0], pt[1]); - gcb.shape(pb); - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testContainsShapeQuery() throws Exception { - // Create a random geometry collection. - Rectangle mbr = xRandomRectangle(random(), xRandomPoint(random()), true); - GeometryCollectionBuilder gcb = createGeometryCollectionWithin(random(), mbr); - - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree" ) - .get(); - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // index the mbr of the collection - EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), - new Coordinate(mbr.getMaxX(), mbr.getMinY())); - docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) - .relation(ShapeRelation.CONTAINS); - SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(response); - - assertThat(response.getHits().getTotalHits().value, greaterThan(0L)); - } - - public void testExistsQuery() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); - SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testShapeFilterWithDefinedGeoCollection() throws Exception { - createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .get(); - - XContentBuilder docSource = jsonBuilder().startObject().startObject("location") - .field("type", "geometrycollection") - .startArray("geometries") - .startObject() - .field("type", "point") - .startArray("coordinates") - .value(100.0).value(0.0) - .endArray() - .endObject() - .startObject() - .field("type", "linestring") - .startArray("coordinates") - .startArray() - .value(101.0).value(0.0) - .endArray() - .startArray() - .value(102.0).value(1.0) - .endArray() - .endArray() - .endObject() - .endArray() - .endObject().endObject(); - client().prepareIndex("test").setId("1") - .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( - "location", - new GeometryCollectionBuilder() - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) - .coordinate(103.0, 3.0).coordinate(103.0, -1.0) - .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery( - "location", - new GeometryCollectionBuilder().polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() - .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) - .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - // no shape - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - } - - public void testPointsOnly() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .field("tree_levels", "6") - .field("distance_error_pct", "0.01") - .field("points_only", true) - .endObject().endObject() - .endObject().endObject()); - - client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random()); - try { - client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - } catch (MapperParsingException e) { - // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown - assertThat(e.getCause().getMessage(), containsString("is configured for points only")); - return; - } - - // test that point was inserted - SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(geoIntersectionQuery("location", shape)) - .get(); - - assertEquals(1, response.getHits().getTotalHits().value); - } - - public void testPointsOnlyExplicit() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .field("tree_levels", "6") - .field("distance_error_pct", "0.01") - .field("points_only", true) - .endObject().endObject() - .endObject().endObject()); - - client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - // MULTIPOINT - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); - client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - // POINT - shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.POINT); - client().prepareIndex("geo_points_only").setId("2") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - // test that point was inserted - SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(matchAllQuery()) - .get(); - - assertEquals(2, response.getHits().getTotalHits().value); - } - - public void testFieldAlias() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.EMPTY, "type", mapping); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("alias", shape)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - - // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("doc") - .startObject("properties") - .startObject("geo").field("type", "geo_shape").endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - - String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( - () -> QueryBuilders.geoShapeQuery( - "geo", - new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) - ).relation(ShapeRelation.WITHIN), - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .startObject("shape") - .field("type", "envelope") - .startArray("coordinates") - .startArray().value(-21).value(44).endArray() - .startArray().value(-39).value(9).endArray() - .endArray() - .endObject() - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - }, - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .field("shape", "BBOX (-21, -39, 44, 9)") - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - } - ); - - SearchResponse response = client().prepareSearch("test") - .setQuery(querySupplier.get()) - .get(); - assertEquals(2, response.getHits().getTotalHits().value); - assertNotEquals("1", response.getHits().getAt(0).getId()); - assertNotEquals("1", response.getHits().getAt(1).getId()); - } } From 478cee77cd823009bf0f7ac7a622e09ca3efc35f Mon Sep 17 00:00:00 2001 From: djptek Date: Mon, 18 Nov 2019 18:17:59 +0100 Subject: [PATCH 02/18] WIP subclassing GeoShapeQueryTests.java --- .../elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java | 5 ++++- .../org/elasticsearch/test/geo/RandomShapeGenerator.java | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java index 4995e574aceb0..df61cf9c293c0 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java @@ -36,6 +36,7 @@ public class GeoShapeGeoPointQueryTests extends GeoShapeQueryTests { + /* public void testIndexPointsFilterRectangle() throws Exception { String mapping = Strings.toString(createMapping()); client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); @@ -356,7 +357,7 @@ public void testRandomGeoCollectionQuery() throws Exception { result.getHits().getTotalHits().value > 0); } - /** tests querying a random geometry collection with a point */ + // ** tests querying a random geometry collection with a point public void testPointQuery() throws Exception { // Create a random geometry collection to index. GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); @@ -663,4 +664,6 @@ public void testEnvelopeSpanningDateline() throws IOException { assertNotEquals("1", response.getHits().getAt(0).getId()); assertNotEquals("1", response.getHits().getAt(1).getId()); } + + */ } diff --git a/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java b/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java index 0d964e8eb6fa7..d9a3da8190dab 100644 --- a/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java +++ b/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java @@ -32,7 +32,7 @@ import org.elasticsearch.common.geo.builders.PointBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder; -import org.elasticsearch.search.geo.GeoShapeQueryTests; +import org.elasticsearch.search.geo.GeoShapeGeoShapeQueryTests; import org.junit.Assert; import org.locationtech.spatial4j.context.jts.JtsSpatialContext; import org.locationtech.spatial4j.distance.DistanceUtils; @@ -154,7 +154,7 @@ private static ShapeBuilder createShape(Random r, Point nearPoint, Rectangle wit /** * Creates a random shape useful for randomized testing, NOTE: exercise caution when using this to build random GeometryCollections * as creating a large random number of random shapes can result in massive resource consumption - * see: {@link GeoShapeQueryTests#testQueryRandomGeoCollection()} + * see: {@link GeoShapeGeoShapeQueryTests#testQueryRandomGeoCollection()} * * The following options are included * @param nearPoint Create a shape near a provided point From ebd06e44089a94b605d6a2d3f77fbb9a4828d14c Mon Sep 17 00:00:00 2001 From: djptek Date: Tue, 19 Nov 2019 13:34:44 +0100 Subject: [PATCH 03/18] WIP subclassing GeoShapeQueryTests.java --- ...ests.java => GeoPointShapeQueryTests.java} | 33 +- .../search/geo/GeoQueryTests.java | 102 +++ .../geo/GeoShapeGeoShapeQueryTests.java | 666 ----------------- .../search/geo/GeoShapeQueryTests.java | 684 ++++++++++++++++-- .../test/geo/RandomShapeGenerator.java | 4 +- 5 files changed, 728 insertions(+), 761 deletions(-) rename server/src/test/java/org/elasticsearch/search/geo/{GeoShapeGeoPointQueryTests.java => GeoPointShapeQueryTests.java} (95%) create mode 100644 server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java delete mode 100644 server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java similarity index 95% rename from server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java rename to server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index df61cf9c293c0..53a702362bb87 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoPointQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -1,40 +1,9 @@ package org.elasticsearch.search.geo; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import org.apache.lucene.geo.GeoTestUtil; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.CheckedSupplier; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.common.geo.SpatialStrategy; -import org.elasticsearch.common.geo.builders.*; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.query.ExistsQueryBuilder; -import org.elasticsearch.index.query.GeoShapeQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.test.geo.RandomShapeGenerator; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.spatial4j.shape.Rectangle; - -import java.io.IOException; -import java.util.Locale; - -import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.elasticsearch.test.geo.RandomShapeGenerator.*; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.Matchers.*; -public class GeoShapeGeoPointQueryTests extends GeoShapeQueryTests { +public class GeoPointShapeQueryTests extends GeoQueryTests { /* public void testIndexPointsFilterRectangle() throws Exception { diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java new file mode 100644 index 0000000000000..f133b265a0ef8 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -0,0 +1,102 @@ +/* + * 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.search.geo; + +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; + +import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.SpatialStrategy; +import org.elasticsearch.common.geo.builders.CoordinatesBuilder; +import org.elasticsearch.common.geo.builders.EnvelopeBuilder; +import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder; +import org.elasticsearch.common.geo.builders.LineStringBuilder; +import org.elasticsearch.common.geo.builders.MultiPointBuilder; +import org.elasticsearch.common.geo.builders.PointBuilder; +import org.elasticsearch.common.geo.builders.PolygonBuilder; +import org.elasticsearch.common.geo.builders.ShapeBuilder; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.query.ExistsQueryBuilder; +import org.elasticsearch.index.query.GeoShapeQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.ESSingleNodeTestCase; +import org.elasticsearch.test.geo.RandomShapeGenerator; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.spatial4j.shape.Rectangle; + +import java.io.IOException; +import java.util.Locale; + +import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; +import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery; +import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; +import static org.elasticsearch.test.geo.RandomShapeGenerator.createGeometryCollectionWithin; +import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomPoint; +import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.nullValue; + +public abstract class GeoQueryTests extends ESSingleNodeTestCase { + protected static final String[] PREFIX_TREES = new String[] { + LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH, + LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE + }; + + protected XContentBuilder createMapping() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape"); + if (randomBoolean()) { + xcb = xcb.field("tree", randomFrom(PREFIX_TREES)) + .field("strategy", randomFrom(SpatialStrategy.RECURSIVE, SpatialStrategy.TERM)); + } + xcb = xcb.endObject().endObject().endObject().endObject(); + + return xcb; + } + + public void testNullShape() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + GetResponse result = client().prepareGet("test", "aNullshape").get(); + assertThat(result.getField("location"), nullValue()); + } +} diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java deleted file mode 100644 index 62cad410f09be..0000000000000 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeGeoShapeQueryTests.java +++ /dev/null @@ -1,666 +0,0 @@ -package org.elasticsearch.search.geo; - -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import org.apache.lucene.geo.GeoTestUtil; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.CheckedSupplier; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.common.geo.SpatialStrategy; -import org.elasticsearch.common.geo.builders.*; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.query.ExistsQueryBuilder; -import org.elasticsearch.index.query.GeoShapeQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.test.geo.RandomShapeGenerator; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.spatial4j.shape.Rectangle; - -import java.io.IOException; -import java.util.Locale; - -import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; -import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.elasticsearch.test.geo.RandomShapeGenerator.*; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.Matchers.*; - -public class GeoShapeGeoShapeQueryTests extends GeoShapeQueryTests { - - public void testIndexPointsFilterRectangle() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() - .field("name", "Document 2") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-45).value(-50).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", shape)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", shape)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - public void testEdgeCases() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .endObject().endObject().endObject().endObject(); - String mapping = Strings.toString(xcb); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() - .field("name", "Blakely Island") - .startObject("location") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-122.83).value(48.57).endArray() - .startArray().value(-122.77).value(48.56).endArray() - .startArray().value(-122.79).value(48.53).endArray() - .startArray().value(-122.83).value(48.57).endArray() // close the polygon - .endArray().endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - EnvelopeBuilder query = new EnvelopeBuilder(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54)); - - // This search would fail if both geoshape indexing and geoshape filtering - // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", query)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); - } - - public void testIndexedShapeReference() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - createIndex("shapes"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - public void testIndexedShapeReferenceSourceDisabled() throws Exception { - XContentBuilder mapping = createMapping(); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); - createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); - assertThat(e.getMessage(), containsString("source disabled")); - } - - 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())); - assertUnmodified(polygon); - - LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder() - .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()); - assertUnmodified(linestring); - } - - private void assertUnmodified(ShapeBuilder builder) throws IOException { - String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - builder.buildS4J(); - String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - assertThat(before, equalTo(after)); - } - - public void testShapeFetchingPath() throws Exception { - createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); - - String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; - - client().prepareIndex("shapes").setId("1") - .setSource( - String.format( - Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location - ), XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().startObject("location") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-20).value(-20).endArray() - .startArray().value(20).value(-20).endArray() - .startArray().value(20).value(20).endArray() - .startArray().value(-20).value(20).endArray() - .startArray().value(-20).value(-20).endArray() - .endArray().endArray() - .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("location"); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - - // now test the query variant - GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testQueryRandomGeoCollection() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - if (randomBoolean()) { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape").get(); - } else { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assumeTrue("Skipping the check for the polygon with a degenerated dimension until " - +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - assertHitCount(result, 1); - } - - 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); - } - } - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - - assumeTrue("Skipping the check for the polygon with a degenerated dimension", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), - usePrefixTrees ? "default" : "quadtree"); - - if (usePrefixTrees == false) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // Create a random geometry collection to query - GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); - queryCollection.shape(new PolygonBuilder(cb)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), - result.getHits().getTotalHits().value > 0); - } - - /** tests querying a random geometry collection with a point */ - public void testPointQuery() throws Exception { - // Create a random geometry collection to index. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; - PointBuilder pb = new PointBuilder(pt[0], pt[1]); - gcb.shape(pb); - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testContainsShapeQuery() throws Exception { - // Create a random geometry collection. - Rectangle mbr = xRandomRectangle(random(), xRandomPoint(random()), true); - GeometryCollectionBuilder gcb = createGeometryCollectionWithin(random(), mbr); - - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree" ) - .get(); - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // index the mbr of the collection - EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), - new Coordinate(mbr.getMaxX(), mbr.getMinY())); - docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) - .relation(ShapeRelation.CONTAINS); - SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(response); - - assertThat(response.getHits().getTotalHits().value, greaterThan(0L)); - } - - public void testExistsQuery() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); - SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testShapeFilterWithDefinedGeoCollection() throws Exception { - createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .get(); - - XContentBuilder docSource = jsonBuilder().startObject().startObject("location") - .field("type", "geometrycollection") - .startArray("geometries") - .startObject() - .field("type", "point") - .startArray("coordinates") - .value(100.0).value(0.0) - .endArray() - .endObject() - .startObject() - .field("type", "linestring") - .startArray("coordinates") - .startArray() - .value(101.0).value(0.0) - .endArray() - .startArray() - .value(102.0).value(1.0) - .endArray() - .endArray() - .endObject() - .endArray() - .endObject().endObject(); - client().prepareIndex("test").setId("1") - .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( - "location", - new GeometryCollectionBuilder() - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) - .coordinate(103.0, 3.0).coordinate(103.0, -1.0) - .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery( - "location", - new GeometryCollectionBuilder().polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() - .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) - .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - // no shape - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - } - - public void testPointsOnly() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .field("tree_levels", "6") - .field("distance_error_pct", "0.01") - .field("points_only", true) - .endObject().endObject() - .endObject().endObject()); - - client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random()); - try { - client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - } catch (MapperParsingException e) { - // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown - assertThat(e.getCause().getMessage(), containsString("is configured for points only")); - return; - } - - // test that point was inserted - SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(geoIntersectionQuery("location", shape)) - .get(); - - assertEquals(1, response.getHits().getTotalHits().value); - } - - public void testPointsOnlyExplicit() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .field("tree_levels", "6") - .field("distance_error_pct", "0.01") - .field("points_only", true) - .endObject().endObject() - .endObject().endObject()); - - client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - // MULTIPOINT - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); - client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - // POINT - shape = RandomShapeGenerator.createShape(random(), ShapeType.POINT); - client().prepareIndex("geo_points_only").setId("2") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - // test that point was inserted - SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(matchAllQuery()) - .get(); - - assertEquals(2, response.getHits().getTotalHits().value); - } - - public void testFieldAlias() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.EMPTY, "type", mapping); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("alias", shape)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - - // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("doc") - .startObject("properties") - .startObject("geo").field("type", "geo_shape").endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - - String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( - () -> QueryBuilders.geoShapeQuery( - "geo", - new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) - ).relation(ShapeRelation.WITHIN), - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .startObject("shape") - .field("type", "envelope") - .startArray("coordinates") - .startArray().value(-21).value(44).endArray() - .startArray().value(-39).value(9).endArray() - .endArray() - .endObject() - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - }, - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .field("shape", "BBOX (-21, -39, 44, 9)") - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - } - ); - - SearchResponse response = client().prepareSearch("test") - .setQuery(querySupplier.get()) - .get(); - assertEquals(2, response.getHits().getTotalHits().value); - assertNotEquals("1", response.getHits().getAt(0).getId()); - assertNotEquals("1", response.getHits().getAt(1).getId()); - } -} diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 5534d8c4c5403..1b8465a77ef09 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -1,53 +1,22 @@ -/* - * 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.search.geo; import com.carrotsearch.randomizedtesting.generators.RandomNumbers; - import org.apache.lucene.geo.GeoTestUtil; -import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.common.geo.SpatialStrategy; -import org.elasticsearch.common.geo.builders.CoordinatesBuilder; -import org.elasticsearch.common.geo.builders.EnvelopeBuilder; -import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder; -import org.elasticsearch.common.geo.builders.LineStringBuilder; -import org.elasticsearch.common.geo.builders.MultiPointBuilder; -import org.elasticsearch.common.geo.builders.PointBuilder; -import org.elasticsearch.common.geo.builders.PolygonBuilder; -import org.elasticsearch.common.geo.builders.ShapeBuilder; +import org.elasticsearch.common.geo.builders.*; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.query.ExistsQueryBuilder; import org.elasticsearch.index.query.GeoShapeQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.geo.RandomShapeGenerator; import org.locationtech.jts.geom.Coordinate; import org.locationtech.spatial4j.shape.Rectangle; @@ -57,46 +26,639 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; -import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery; -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; -import static org.elasticsearch.test.geo.RandomShapeGenerator.createGeometryCollectionWithin; -import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomPoint; -import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.test.geo.RandomShapeGenerator.*; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.nullValue; - -public abstract class GeoShapeQueryTests extends ESSingleNodeTestCase { - protected static final String[] PREFIX_TREES = new String[] { - LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH, - LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE - }; - - protected XContentBuilder createMapping() throws Exception { +import static org.hamcrest.Matchers.*; + +public class GeoShapeQueryTests extends GeoQueryTests { + + public void testIndexPointsFilterRectangle() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() + .field("name", "Document 2") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-45).value(-50).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("location", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testEdgeCases() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") .startObject("properties").startObject("location") - .field("type", "geo_shape"); - if (randomBoolean()) { - xcb = xcb.field("tree", randomFrom(PREFIX_TREES)) - .field("strategy", randomFrom(SpatialStrategy.RECURSIVE, SpatialStrategy.TERM)); - } - xcb = xcb.endObject().endObject().endObject().endObject(); + .field("type", "geo_shape") + .endObject().endObject().endObject().endObject(); + String mapping = Strings.toString(xcb); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); - return xcb; + client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() + .field("name", "Blakely Island") + .startObject("location") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-122.83).value(48.57).endArray() + .startArray().value(-122.77).value(48.56).endArray() + .startArray().value(-122.79).value(48.53).endArray() + .startArray().value(-122.83).value(48.57).endArray() // close the polygon + .endArray().endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder query = new EnvelopeBuilder(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54)); + + // This search would fail if both geoshape indexing and geoshape filtering + // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", query)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); } - public void testNullShape() throws Exception { + public void testIndexedShapeReference() throws Exception { String mapping = Strings.toString(createMapping()); client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + createIndex("shapes"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("location") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("location", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testIndexedShapeReferenceSourceDisabled() throws Exception { + XContentBuilder mapping = createMapping(); + client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); + createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); ensureGreen(); - client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") + .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); + assertThat(e.getMessage(), containsString("source disabled")); + } + + 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())); + assertUnmodified(polygon); + + LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder() + .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()); + assertUnmodified(linestring); + } + + private void assertUnmodified(ShapeBuilder builder) throws IOException { + String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); + builder.buildS4J(); + String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); + assertThat(before, equalTo(after)); + } + + public void testShapeFetchingPath() throws Exception { + createIndex("shapes"); + client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); + + String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; + + client().prepareIndex("shapes").setId("1") + .setSource( + String.format( + Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location + ), XContentType.JSON) .setRefreshPolicy(IMMEDIATE).get(); - GetResponse result = client().prepareGet("test", "aNullshape").get(); - assertThat(result.getField("location"), nullValue()); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().startObject("location") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-20).value(-20).endArray() + .startArray().value(20).value(-20).endArray() + .startArray().value(20).value(20).endArray() + .startArray().value(-20).value(20).endArray() + .startArray().value(-20).value(-20).endArray() + .endArray().endArray() + .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("location"); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.location"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + + // now test the query variant + GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("location", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.location"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testQueryRandomGeoCollection() throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + if (randomBoolean()) { + client().admin().indices().prepareCreate("test") + .addMapping("type", "location", "type=geo_shape").get(); + } else { + client().admin().indices().prepareCreate("test") + .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assumeTrue("Skipping the check for the polygon with a degenerated dimension until " + +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + assertHitCount(result, 1); + } + + 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); + } + } + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + + assumeTrue("Skipping the check for the polygon with a degenerated dimension", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), + usePrefixTrees ? "default" : "quadtree"); + + if (usePrefixTrees == false) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // Create a random geometry collection to query + GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); + queryCollection.shape(new PolygonBuilder(cb)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), + result.getHits().getTotalHits().value > 0); + } + + /** tests querying a random geometry collection with a point */ + public void testPointQuery() throws Exception { + // Create a random geometry collection to index. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; + PointBuilder pb = new PointBuilder(pt[0], pt[1]); + gcb.shape(pb); + if (randomBoolean()) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testContainsShapeQuery() throws Exception { + // Create a random geometry collection. + Rectangle mbr = xRandomRectangle(random(), xRandomPoint(random()), true); + GeometryCollectionBuilder gcb = createGeometryCollectionWithin(random(), mbr); + + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree" ) + .get(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // index the mbr of the collection + EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), + new Coordinate(mbr.getMaxX(), mbr.getMinY())); + docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) + .relation(ShapeRelation.CONTAINS); + SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(response); + + assertThat(response.getHits().getTotalHits().value, greaterThan(0L)); + } + + public void testExistsQuery() throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + if (randomBoolean()) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); + SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testShapeFilterWithDefinedGeoCollection() throws Exception { + createIndex("shapes"); + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .get(); + + XContentBuilder docSource = jsonBuilder().startObject().startObject("location") + .field("type", "geometrycollection") + .startArray("geometries") + .startObject() + .field("type", "point") + .startArray("coordinates") + .value(100.0).value(0.0) + .endArray() + .endObject() + .startObject() + .field("type", "linestring") + .startArray("coordinates") + .startArray() + .value(101.0).value(0.0) + .endArray() + .startArray() + .value(102.0).value(1.0) + .endArray() + .endArray() + .endObject() + .endArray() + .endObject().endObject(); + client().prepareIndex("test").setId("1") + .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( + "location", + new GeometryCollectionBuilder() + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) + .coordinate(103.0, 3.0).coordinate(103.0, -1.0) + .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery( + "location", + new GeometryCollectionBuilder().polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() + .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) + .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + // no shape + filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + } + + public void testPointsOnly() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .field("tree_levels", "6") + .field("distance_error_pct", "0.01") + .field("points_only", true) + .endObject().endObject() + .endObject().endObject()); + + client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random()); + try { + client().prepareIndex("geo_points_only").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + } catch (MapperParsingException e) { + // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown + assertThat(e.getCause().getMessage(), containsString("is configured for points only")); + return; + } + + // test that point was inserted + SearchResponse response = client().prepareSearch("geo_points_only") + .setQuery(geoIntersectionQuery("location", shape)) + .get(); + + assertEquals(1, response.getHits().getTotalHits().value); + } + + public void testPointsOnlyExplicit() throws Exception { + String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .field("tree_levels", "6") + .field("distance_error_pct", "0.01") + .field("points_only", true) + .endObject().endObject() + .endObject().endObject()); + + client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); + ensureGreen(); + + // MULTIPOINT + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); + client().prepareIndex("geo_points_only").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + // POINT + shape = RandomShapeGenerator.createShape(random(), ShapeType.POINT); + client().prepareIndex("geo_points_only").setId("2") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + // test that point was inserted + SearchResponse response = client().prepareSearch("geo_points_only") + .setQuery(matchAllQuery()) + .get(); + + assertEquals(2, response.getHits().getTotalHits().value); + } + + public void testFieldAlias() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() + .endObject() + .endObject(); + + createIndex("test", Settings.EMPTY, "type", mapping); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("alias", shape)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } + + // Test for issue #34418 + public void testEnvelopeSpanningDateline() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("doc") + .startObject("properties") + .startObject("geo").field("type", "geo_shape").endObject() + .endObject() + .endObject() + .endObject(); + + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + + String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( + () -> QueryBuilders.geoShapeQuery( + "geo", + new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) + ).relation(ShapeRelation.WITHIN), + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .startObject("shape") + .field("type", "envelope") + .startArray("coordinates") + .startArray().value(-21).value(44).endArray() + .startArray().value(-39).value(9).endArray() + .endArray() + .endObject() + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + }, + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .field("shape", "BBOX (-21, -39, 44, 9)") + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + } + ); + + SearchResponse response = client().prepareSearch("test") + .setQuery(querySupplier.get()) + .get(); + assertEquals(2, response.getHits().getTotalHits().value); + assertNotEquals("1", response.getHits().getAt(0).getId()); + assertNotEquals("1", response.getHits().getAt(1).getId()); } } diff --git a/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java b/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java index d9a3da8190dab..0d964e8eb6fa7 100644 --- a/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java +++ b/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java @@ -32,7 +32,7 @@ import org.elasticsearch.common.geo.builders.PointBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder; -import org.elasticsearch.search.geo.GeoShapeGeoShapeQueryTests; +import org.elasticsearch.search.geo.GeoShapeQueryTests; import org.junit.Assert; import org.locationtech.spatial4j.context.jts.JtsSpatialContext; import org.locationtech.spatial4j.distance.DistanceUtils; @@ -154,7 +154,7 @@ private static ShapeBuilder createShape(Random r, Point nearPoint, Rectangle wit /** * Creates a random shape useful for randomized testing, NOTE: exercise caution when using this to build random GeometryCollections * as creating a large random number of random shapes can result in massive resource consumption - * see: {@link GeoShapeGeoShapeQueryTests#testQueryRandomGeoCollection()} + * see: {@link GeoShapeQueryTests#testQueryRandomGeoCollection()} * * The following options are included * @param nearPoint Create a shape near a provided point From 5d3c189b8cdaf9d644af94399d15e6207a19594d Mon Sep 17 00:00:00 2001 From: djptek Date: Tue, 19 Nov 2019 20:58:13 +0100 Subject: [PATCH 04/18] WIP writing GeoPointShapeQueryTests.java --- .../search/geo/GeoPointShapeQueryTests.java | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index 53a702362bb87..b2a512947b3c3 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -1,11 +1,42 @@ package org.elasticsearch.search.geo; +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.builders.*; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.query.ExistsQueryBuilder; +import org.elasticsearch.index.query.GeoShapeQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.geo.RandomShapeGenerator; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.spatial4j.shape.Rectangle; + +import java.io.IOException; +import java.util.Locale; + +import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.test.geo.RandomShapeGenerator.*; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.Matchers.*; + import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; public class GeoPointShapeQueryTests extends GeoQueryTests { - /* public void testIndexPointsFilterRectangle() throws Exception { String mapping = Strings.toString(createMapping()); client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); @@ -29,8 +60,9 @@ public void testIndexPointsFilterRectangle() throws Exception { EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + // This is deprecated... go fix SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", shape)) + .setQuery(geoShapeQuery("location", shape)) .get(); assertSearchResponse(searchResponse); @@ -48,6 +80,7 @@ public void testIndexPointsFilterRectangle() throws Exception { assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); } + /* public void testEdgeCases() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") .startObject("properties").startObject("location") From ab60f0679b0837885dde114f8870e6484ba4077d Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 20 Nov 2019 20:07:45 +0100 Subject: [PATCH 05/18] Added Failing Test testIndexPointsFilterRectangle in Class org.elasticsearch.search.geo.GeoPointShapeQueryTests --- .../search/geo/GeoPointShapeQueryTests.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index b2a512947b3c3..bb031fefa5a4d 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -39,28 +39,23 @@ public class GeoPointShapeQueryTests extends GeoQueryTests { public void testIndexPointsFilterRectangle() throws Exception { String mapping = Strings.toString(createMapping()); + // where does the mapping ensure geo_shape type for the location field, a template? client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); ensureGreen(); client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); + .field("name", "Document 1") + .startArray("location").value(-30).value(-30).endArray() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() - .field("name", "Document 2") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-45).value(-50).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); + .field("name", "Document 2") + .startArray("location").value(-45).value(-50).endArray() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - // This is deprecated... go fix + // This is deprecated...? go fix SearchResponse searchResponse = client().prepareSearch("test") .setQuery(geoShapeQuery("location", shape)) .get(); From 24b95358fca9a5b1f266651ac507fe17115a5e35 Mon Sep 17 00:00:00 2001 From: djptek Date: Sat, 23 Nov 2019 20:40:19 +0100 Subject: [PATCH 06/18] permit GeoShapeQueryBuilder to accept a geo_point -> class_cast_exception raised, see org.elasticsearch.index.query.QueryShardContext.toQuery --- .../org/elasticsearch/index/query/GeoShapeQueryBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java index 78c727a90212b..b1c14116c747a 100644 --- a/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java @@ -35,6 +35,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.geometry.Geometry; import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper; +import org.elasticsearch.index.mapper.GeoPointFieldMapper; import org.elasticsearch.index.mapper.GeoShapeFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; @@ -197,7 +198,8 @@ protected GeoShapeQueryBuilder newShapeQueryBuilder(String fieldName, Supplier Date: Mon, 2 Dec 2019 19:03:56 +0100 Subject: [PATCH 07/18] added @Override protected XContentBuilder createMapping in GeoPointShapeQueryTests --- .../search/geo/GeoPointShapeQueryTests.java | 30 ++++++++----------- .../search/geo/GeoQueryTests.java | 13 +------- .../search/geo/GeoShapeQueryTests.java | 15 ++++++++++ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index bb031fefa5a4d..99e8c055c7575 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -1,34 +1,17 @@ package org.elasticsearch.search.geo; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import org.apache.lucene.geo.GeoTestUtil; -import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.SpatialStrategy; import org.elasticsearch.common.geo.builders.*; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.query.ExistsQueryBuilder; -import org.elasticsearch.index.query.GeoShapeQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.test.geo.RandomShapeGenerator; import org.locationtech.jts.geom.Coordinate; -import org.locationtech.spatial4j.shape.Rectangle; - -import java.io.IOException; -import java.util.Locale; import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.elasticsearch.test.geo.RandomShapeGenerator.*; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; import static org.hamcrest.Matchers.*; @@ -75,6 +58,16 @@ public void testIndexPointsFilterRectangle() throws Exception { assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); } + @Override + protected XContentBuilder createMapping() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_point") + .endObject().endObject().endObject().endObject(); + + return xcb; + } + /* public void testEdgeCases() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") @@ -663,4 +656,5 @@ public void testEnvelopeSpanningDateline() throws IOException { } */ + } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index f133b265a0ef8..18a065601a263 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -76,18 +76,7 @@ public abstract class GeoQueryTests extends ESSingleNodeTestCase { LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE }; - protected XContentBuilder createMapping() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape"); - if (randomBoolean()) { - xcb = xcb.field("tree", randomFrom(PREFIX_TREES)) - .field("strategy", randomFrom(SpatialStrategy.RECURSIVE, SpatialStrategy.TERM)); - } - xcb = xcb.endObject().endObject().endObject().endObject(); - - return xcb; - } + protected abstract XContentBuilder createMapping() throws Exception; public void testNullShape() throws Exception { String mapping = Strings.toString(createMapping()); diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 1b8465a77ef09..6d5dde11227c8 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -7,6 +7,7 @@ import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.SpatialStrategy; import org.elasticsearch.common.geo.builders.*; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -661,4 +662,18 @@ public void testEnvelopeSpanningDateline() throws IOException { assertNotEquals("1", response.getHits().getAt(0).getId()); assertNotEquals("1", response.getHits().getAt(1).getId()); } + + @Override + protected XContentBuilder createMapping() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") + .startObject("properties").startObject("location") + .field("type", "geo_shape"); + if (randomBoolean()) { + xcb = xcb.field("tree", randomFrom(PREFIX_TREES)) + .field("strategy", randomFrom(SpatialStrategy.RECURSIVE, SpatialStrategy.TERM)); + } + xcb = xcb.endObject().endObject().endObject().endObject(); + + return xcb; + } } From ddc9e8cc08d288cbc0b03bd49880a16b7fba27f1 Mon Sep 17 00:00:00 2001 From: djptek Date: Tue, 7 Jan 2020 16:26:12 +0100 Subject: [PATCH 08/18] repeat refactor post type removal and remove remaining types from GeoShapeQueryTests.java --- .../search/geo/GeoPointShapeQueryTests.java | 13 +- .../search/geo/GeoQueryTests.java | 4 +- .../search/geo/GeoShapeQueryTests.java | 115 ++++++++++-------- 3 files changed, 75 insertions(+), 57 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index 99e8c055c7575..ca050da5a600e 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -13,8 +13,11 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.*; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.Matchers.*; - +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.nullValue; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; @@ -23,7 +26,7 @@ public class GeoPointShapeQueryTests extends GeoQueryTests { public void testIndexPointsFilterRectangle() throws Exception { String mapping = Strings.toString(createMapping()); // where does the mapping ensure geo_shape type for the location field, a template? - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); ensureGreen(); client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() @@ -60,10 +63,10 @@ public void testIndexPointsFilterRectangle() throws Exception { @Override protected XContentBuilder createMapping() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("location") .field("type", "geo_point") - .endObject().endObject().endObject().endObject(); + .endObject().endObject().endObject(); return xcb; } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index 18a065601a263..0d74479b842aa 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -65,6 +65,7 @@ import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; @@ -80,7 +81,7 @@ public abstract class GeoQueryTests extends ESSingleNodeTestCase { public void testNullShape() throws Exception { String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) @@ -88,4 +89,5 @@ public void testNullShape() throws Exception { GetResponse result = client().prepareGet("test", "aNullshape").get(); assertThat(result.getField("location"), nullValue()); } + } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 612973c0b2362..a1f27536f2a1e 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -55,6 +55,8 @@ import java.io.IOException; import java.util.Locale; +import static org.apache.lucene.util.LuceneTestCase.expectThrows; +import static org.apache.lucene.util.LuceneTestCase.random; import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; @@ -65,6 +67,7 @@ import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; @@ -89,20 +92,8 @@ private XContentBuilder createMapping() throws Exception { return xcb; } - public void testNullShape() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - GetResponse result = client().prepareGet("test", "aNullshape").get(); - assertThat(result.getField("location"), nullValue()); - } - public void testIndexPointsFilterRectangle() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); ensureGreen(); client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() @@ -179,8 +170,7 @@ public void testEdgeCases() throws Exception { } public void testIndexedShapeReference() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); createIndex("shapes"); ensureGreen(); @@ -216,8 +206,7 @@ public void testIndexedShapeReference() throws Exception { } public void testIndexedShapeReferenceSourceDisabled() throws Exception { - XContentBuilder mapping = createMapping(); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); ensureGreen(); @@ -252,8 +241,7 @@ private void assertUnmodified(ShapeBuilder builder) throws IOException { public void testShapeFetchingPath() throws Exception { createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); - + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; client().prepareIndex("shapes").setId("1") @@ -398,10 +386,15 @@ public void testRandomGeoCollectionQuery() throws Exception { usePrefixTrees ? "default" : "quadtree"); if (usePrefixTrees == false) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) .execute().actionGet(); } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", "quadtree") + .endObject().endObject().endObject(); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) .execute().actionGet(); } @@ -428,10 +421,15 @@ public void testPointQuery() throws Exception { PointBuilder pb = new PointBuilder(pt[0], pt[1]); gcb.shape(pb); if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) .execute().actionGet(); } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", "quadtree") + .endObject().endObject().endObject(); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) .execute().actionGet(); } XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); @@ -465,10 +463,15 @@ public void testContainsShapeQuery() throws Exception { } if (usePrefixTrees) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", "quadtree") + .endObject().endObject().endObject(); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) .execute().actionGet(); } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) .execute().actionGet(); } @@ -497,10 +500,15 @@ public void testExistsQuery() throws Exception { logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) .execute().actionGet(); } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", "quadtree") + .endObject().endObject().endObject(); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) .execute().actionGet(); } @@ -515,8 +523,13 @@ public void testExistsQuery() throws Exception { public void testShapeFilterWithDefinedGeoCollection() throws Exception { createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .get(); + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("location") + .field("type", "geo_shape") + .field("tree", "quadtree") + .endObject().endObject().endObject(); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) + .execute().actionGet(); XContentBuilder docSource = jsonBuilder().startObject().startObject("location") .field("type", "geometrycollection") @@ -651,22 +664,22 @@ public void testPointsOnlyExplicit() throws Exception { } public void testFieldAlias() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() + createIndex("test"); + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") .endObject() .endObject() .endObject(); - createIndex("test", Settings.EMPTY, "type", mapping); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) + .execute().actionGet(); ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); client().prepareIndex("test").setId("1") @@ -681,15 +694,15 @@ public void testFieldAlias() throws IOException { // Test for issue #34418 public void testEnvelopeSpanningDateline() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("doc") - .startObject("properties") - .startObject("geo").field("type", "geo_shape").endObject() - .endObject() + Settings settings = Settings.builder().put("index.number_of_shards", 1).build(); + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("geo").field("type", "geo_shape").endObject() .endObject() .endObject(); - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + client().admin().indices().prepareCreate("test").setSettings(settings).setMapping(xcb.toString()) + .execute().actionGet(); String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + "\"type\": \"Point\"\r\n" + "}}"; @@ -749,15 +762,15 @@ public void testEnvelopeSpanningDateline() throws IOException { } public void testGeometryCollectionRelations() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("doc") + Settings settings = Settings.builder().put("index.number_of_shards", 1).build(); + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties") .startObject("geo").field("type", "geo_shape").endObject() .endObject() - .endObject() .endObject(); - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + client().admin().indices().prepareCreate("test").setSettings(settings).setMapping(xcb.toString()) + .execute().actionGet(); EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10)); From 0f3bd915b56e3c5ca26fc19d0a63a66003e3f0cc Mon Sep 17 00:00:00 2001 From: djptek Date: Tue, 7 Jan 2020 16:27:59 +0100 Subject: [PATCH 09/18] tidy GeoPointShapeQueryTests.java --- .../search/geo/GeoPointShapeQueryTests.java | 589 ------------------ 1 file changed, 589 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index ca050da5a600e..a740630b30892 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -71,593 +71,4 @@ protected XContentBuilder createMapping() throws Exception { return xcb; } - /* - public void testEdgeCases() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .endObject().endObject().endObject().endObject(); - String mapping = Strings.toString(xcb); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() - .field("name", "Blakely Island") - .startObject("location") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-122.83).value(48.57).endArray() - .startArray().value(-122.77).value(48.56).endArray() - .startArray().value(-122.79).value(48.53).endArray() - .startArray().value(-122.83).value(48.57).endArray() // close the polygon - .endArray().endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - EnvelopeBuilder query = new EnvelopeBuilder(new Coordinate(-122.88, 48.62), new Coordinate(-122.82, 48.54)); - - // This search would fail if both geoshape indexing and geoshape filtering - // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", query)) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); - } - - public void testIndexedShapeReference() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get(); - createIndex("shapes"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("location") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - public void testIndexedShapeReferenceSourceDisabled() throws Exception { - XContentBuilder mapping = createMapping(); - client().admin().indices().prepareCreate("test").addMapping("type1", mapping).get(); - createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); - assertThat(e.getMessage(), containsString("source disabled")); - } - - 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())); - assertUnmodified(polygon); - - LineStringBuilder linestring = new LineStringBuilder(new CoordinatesBuilder() - .coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()); - assertUnmodified(linestring); - } - - private void assertUnmodified(ShapeBuilder builder) throws IOException { - String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - builder.buildS4J(); - String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - assertThat(before, equalTo(after)); - } - - public void testShapeFetchingPath() throws Exception { - createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("_doc", "location", "type=geo_shape").get(); - - String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; - - client().prepareIndex("shapes").setId("1") - .setSource( - String.format( - Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location - ), XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().startObject("location") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-20).value(-20).endArray() - .startArray().value(20).value(-20).endArray() - .startArray().value(20).value(20).endArray() - .startArray().value(-20).value(20).endArray() - .startArray().value(-20).value(-20).endArray() - .endArray().endArray() - .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("location"); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - - // now test the query variant - GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testQueryRandomGeoCollection() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - if (randomBoolean()) { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape").get(); - } else { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assumeTrue("Skipping the check for the polygon with a degenerated dimension until " - +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - assertHitCount(result, 1); - } - - 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); - } - } - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - - assumeTrue("Skipping the check for the polygon with a degenerated dimension", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), - usePrefixTrees ? "default" : "quadtree"); - - if (usePrefixTrees == false) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // Create a random geometry collection to query - GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); - queryCollection.shape(new PolygonBuilder(cb)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), - result.getHits().getTotalHits().value > 0); - } - - // ** tests querying a random geometry collection with a point - public void testPointQuery() throws Exception { - // Create a random geometry collection to index. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; - PointBuilder pb = new PointBuilder(pt[0], pt[1]); - gcb.shape(pb); - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testContainsShapeQuery() throws Exception { - // Create a random geometry collection. - Rectangle mbr = xRandomRectangle(random(), xRandomPoint(random()), true); - GeometryCollectionBuilder gcb = createGeometryCollectionWithin(random(), mbr); - - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree" ) - .get(); - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // index the mbr of the collection - EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), - new Coordinate(mbr.getMaxX(), mbr.getMinY())); - docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) - .relation(ShapeRelation.CONTAINS); - SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(response); - - assertThat(response.getHits().getTotalHits().value, greaterThan(0L)); - } - - public void testExistsQuery() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); - SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testShapeFilterWithDefinedGeoCollection() throws Exception { - createIndex("shapes"); - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .get(); - - XContentBuilder docSource = jsonBuilder().startObject().startObject("location") - .field("type", "geometrycollection") - .startArray("geometries") - .startObject() - .field("type", "point") - .startArray("coordinates") - .value(100.0).value(0.0) - .endArray() - .endObject() - .startObject() - .field("type", "linestring") - .startArray("coordinates") - .startArray() - .value(101.0).value(0.0) - .endArray() - .startArray() - .value(102.0).value(1.0) - .endArray() - .endArray() - .endObject() - .endArray() - .endObject().endObject(); - client().prepareIndex("test").setId("1") - .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( - "location", - new GeometryCollectionBuilder() - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) - .coordinate(103.0, 3.0).coordinate(103.0, -1.0) - .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery( - "location", - new GeometryCollectionBuilder().polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() - .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) - .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - // no shape - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - } - - public void testPointsOnly() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .field("tree_levels", "6") - .field("distance_error_pct", "0.01") - .field("points_only", true) - .endObject().endObject() - .endObject().endObject()); - - client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random()); - try { - client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - } catch (MapperParsingException e) { - // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown - assertThat(e.getCause().getMessage(), containsString("is configured for points only")); - return; - } - - // test that point was inserted - SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(geoIntersectionQuery("location", shape)) - .get(); - - assertEquals(1, response.getHits().getTotalHits().value); - } - - public void testPointsOnlyExplicit() throws Exception { - String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type1") - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .field("tree_levels", "6") - .field("distance_error_pct", "0.01") - .field("points_only", true) - .endObject().endObject() - .endObject().endObject()); - - client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).get(); - ensureGreen(); - - // MULTIPOINT - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); - client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - // POINT - shape = RandomShapeGenerator.createShape(random(), ShapeType.POINT); - client().prepareIndex("geo_points_only").setId("2") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - // test that point was inserted - SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(matchAllQuery()) - .get(); - - assertEquals(2, response.getHits().getTotalHits().value); - } - - public void testFieldAlias() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.EMPTY, "type", mapping); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), ShapeType.MULTIPOINT); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("alias", shape)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - - // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("doc") - .startObject("properties") - .startObject("geo").field("type", "geo_shape").endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - - String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( - () -> QueryBuilders.geoShapeQuery( - "geo", - new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) - ).relation(ShapeRelation.WITHIN), - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .startObject("shape") - .field("type", "envelope") - .startArray("coordinates") - .startArray().value(-21).value(44).endArray() - .startArray().value(-39).value(9).endArray() - .endArray() - .endObject() - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - }, - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .field("shape", "BBOX (-21, -39, 44, 9)") - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - } - ); - - SearchResponse response = client().prepareSearch("test") - .setQuery(querySupplier.get()) - .get(); - assertEquals(2, response.getHits().getTotalHits().value); - assertNotEquals("1", response.getHits().getAt(0).getId()); - assertNotEquals("1", response.getHits().getAt(1).getId()); - } - - */ - } From 6d68e7febd1033882c125def51cc604e8ecaeac1 Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 8 Jan 2020 11:06:11 +0100 Subject: [PATCH 10/18] interim checkin, still failing tests --- .../search/geo/GeoShapeQueryTests.java | 229 ++++++++---------- 1 file changed, 107 insertions(+), 122 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index a1f27536f2a1e..605d17e1c0c7d 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -81,24 +81,48 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase { private XContentBuilder createMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") + .startObject("properties").startObject("geo") + .field("type", "geo_shape") + .endObject() + .endObject() + .endObject(); + + return xcb; + } + + private XContentBuilder createRandomMapping() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("geo") .field("type", "geo_shape"); if (randomBoolean()) { xcb = xcb.field("tree", randomFrom(PREFIX_TREES)) - .field("strategy", randomFrom(SpatialStrategy.RECURSIVE, SpatialStrategy.TERM)); + .field("strategy", randomFrom(SpatialStrategy.RECURSIVE, SpatialStrategy.TERM)); } xcb = xcb.endObject().endObject().endObject(); return xcb; } + private XContentBuilder createQuadtreeMapping() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("geo") + .field("type", "geo_shape") + .field("tree", LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE) + .endObject() + .endObject() + .endObject(); + + return xcb; + } + public void testIndexPointsFilterRectangle() throws Exception { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); + String mapping = Strings.toString(createRandomMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() .field("name", "Document 1") - .startObject("location") + .startObject("geo") .field("type", "point") .startArray("coordinates").value(-30).value(-30).endArray() .endObject() @@ -106,7 +130,7 @@ public void testIndexPointsFilterRectangle() throws Exception { client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() .field("name", "Document 2") - .startObject("location") + .startObject("geo") .field("type", "point") .startArray("coordinates").value(-45).value(-50).endArray() .endObject() @@ -115,7 +139,7 @@ public void testIndexPointsFilterRectangle() throws Exception { EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", shape)) + .setQuery(geoIntersectionQuery("geo", shape)) .get(); assertSearchResponse(searchResponse); @@ -124,7 +148,7 @@ public void testIndexPointsFilterRectangle() throws Exception { assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", shape)) + .setQuery(geoShapeQuery("geo", shape)) .get(); assertSearchResponse(searchResponse); @@ -135,7 +159,7 @@ public void testIndexPointsFilterRectangle() throws Exception { public void testEdgeCases() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") + .startObject("properties").startObject("geo") .field("type", "geo_shape") .endObject().endObject().endObject(); String mapping = Strings.toString(xcb); @@ -144,7 +168,7 @@ public void testEdgeCases() throws Exception { client().prepareIndex("test").setId("blakely").setSource(jsonBuilder().startObject() .field("name", "Blakely Island") - .startObject("location") + .startObject("geo") .field("type", "polygon") .startArray("coordinates").startArray() .startArray().value(-122.83).value(48.57).endArray() @@ -160,7 +184,7 @@ public void testEdgeCases() throws Exception { // This search would fail if both geoshape indexing and geoshape filtering // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", query)) + .setQuery(geoIntersectionQuery("geo", query)) .get(); assertSearchResponse(searchResponse); @@ -170,7 +194,8 @@ public void testEdgeCases() throws Exception { } public void testIndexedShapeReference() throws Exception { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); + String mapping = Strings.toString(createRandomMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); createIndex("shapes"); ensureGreen(); @@ -180,14 +205,14 @@ public void testIndexedShapeReference() throws Exception { .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() .field("name", "Document 1") - .startObject("location") + .startObject("geo") .field("type", "point") .startArray("coordinates").value(-30).value(-30).endArray() .endObject() .endObject()).setRefreshPolicy(IMMEDIATE).get(); SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")) + .setQuery(geoIntersectionQuery("geo", "Big_Rectangle")) .get(); assertSearchResponse(searchResponse); @@ -196,7 +221,7 @@ public void testIndexedShapeReference() throws Exception { assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", "Big_Rectangle")) + .setQuery(geoShapeQuery("geo", "Big_Rectangle")) .get(); assertSearchResponse(searchResponse); @@ -206,7 +231,8 @@ public void testIndexedShapeReference() throws Exception { } public void testIndexedShapeReferenceSourceDisabled() throws Exception { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); + String mapping = Strings.toString(createRandomMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); ensureGreen(); @@ -216,7 +242,7 @@ public void testIndexedShapeReferenceSourceDisabled() throws Exception { .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().prepareSearch("test") - .setQuery(geoIntersectionQuery("location", "Big_Rectangle")).get()); + .setQuery(geoIntersectionQuery("geo", "Big_Rectangle")).get()); assertThat(e.getMessage(), containsString("source disabled")); } @@ -241,7 +267,8 @@ private void assertUnmodified(ShapeBuilder builder) throws IOException { public void testShapeFetchingPath() throws Exception { createIndex("shapes"); - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); + String mapping = Strings.toString(createRandomMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; client().prepareIndex("shapes").setId("1") @@ -251,7 +278,7 @@ public void testShapeFetchingPath() throws Exception { ), XContentType.JSON) .setRefreshPolicy(IMMEDIATE).get(); client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().startObject("location") + .setSource(jsonBuilder().startObject().startObject("geo") .field("type", "polygon") .startArray("coordinates").startArray() .startArray().value(-20).value(-20).endArray() @@ -262,28 +289,28 @@ public void testShapeFetchingPath() throws Exception { .endArray().endArray() .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") - .indexedShapePath("location"); + .indexedShapePath("geo"); SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") .indexedShapePath("1.location"); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") .indexedShapePath("1.2.location"); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("location", "1").relation(ShapeRelation.INTERSECTS) + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") .indexedShapePath("1.2.3.location"); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) @@ -292,25 +319,25 @@ public void testShapeFetchingPath() throws Exception { assertHitCount(result, 1); // now test the query variant - GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("location", "1") + GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") - .indexedShapePath("location"); + .indexedShapePath("geo"); result = client().prepareSearch("test").setQuery(query).get(); assertSearchResponse(result); assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") + query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") .indexedShapePath("1.location"); result = client().prepareSearch("test").setQuery(query).get(); assertSearchResponse(result); assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") + query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") .indexedShapePath("1.2.location"); result = client().prepareSearch("test").setQuery(query).get(); assertSearchResponse(result); assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("location", "1") + query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") .indexedShapePath("1.2.3.location"); result = client().prepareSearch("test").setQuery(query).get(); @@ -330,20 +357,16 @@ public void testQueryRandomGeoCollection() throws Exception { logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - if (randomBoolean()) { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape").get(); - } else { - client().admin().indices().prepareCreate("test") - .addMapping("type", "location", "type=geo_shape,tree=quadtree").get(); - } + String mapping = Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", filterShape); + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape); geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); assertSearchResponse(result); @@ -385,27 +408,19 @@ public void testRandomGeoCollectionQuery() throws Exception { logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), usePrefixTrees ? "default" : "quadtree"); - if (usePrefixTrees == false) { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) - .execute().actionGet(); - } else { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", "quadtree") - .endObject().endObject().endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) - .execute().actionGet(); - } + // don't use random mapping as permits quadtree + String mapping = Strings.toString(usePrefixTrees ? createQuadtreeMapping() : createMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); // Create a random geometry collection to query GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); queryCollection.shape(new PolygonBuilder(cb)); - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", queryCollection); geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); assertSearchResponse(result); @@ -420,22 +435,16 @@ public void testPointQuery() throws Exception { double[] pt = new double[] {GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude()}; PointBuilder pb = new PointBuilder(pt[0], pt[1]); gcb.shape(pb); - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) - .execute().actionGet(); - } else { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", "quadtree") - .endObject().endObject().endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) - .execute().actionGet(); - } - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + + // don't use random as permits quadtree + String mapping = Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", pb); + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", pb); geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); assertSearchResponse(result); @@ -462,30 +471,22 @@ public void testContainsShapeQuery() throws Exception { } } - if (usePrefixTrees) { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", "quadtree") - .endObject().endObject().endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) - .execute().actionGet(); - } + // don't use random mapping as permits quadtree + String mapping = Strings.toString(usePrefixTrees ? createQuadtreeMapping() : createMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); // index the mbr of the collection EnvelopeBuilder env = new EnvelopeBuilder(new Coordinate(mbr.getMinX(), mbr.getMaxY()), new Coordinate(mbr.getMaxX(), mbr.getMinY())); - docSource = env.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + docSource = env.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("2").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); ShapeBuilder filterShape = (gcb.getShapeAt(randomIntBetween(0, gcb.numShapes() - 1))); - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("location", filterShape) + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("geo", filterShape) .relation(ShapeRelation.CONTAINS); SearchResponse response = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); @@ -499,23 +500,14 @@ public void testExistsQuery() throws Exception { GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - if (randomBoolean()) { - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()) - .execute().actionGet(); - } else { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") - .field("type", "geo_shape") - .field("tree", "quadtree") - .endObject().endObject().endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) - .execute().actionGet(); - } + String mapping = Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - ExistsQueryBuilder eqb = QueryBuilders.existsQuery("location"); + ExistsQueryBuilder eqb = QueryBuilders.existsQuery("geo"); SearchResponse result = client().prepareSearch("test").setQuery(eqb).get(); assertSearchResponse(result); assertHitCount(result, 1); @@ -524,14 +516,14 @@ public void testExistsQuery() throws Exception { public void testShapeFilterWithDefinedGeoCollection() throws Exception { createIndex("shapes"); XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") + .startObject("properties").startObject("geo") .field("type", "geo_shape") .field("tree", "quadtree") .endObject().endObject().endObject(); client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) .execute().actionGet(); - XContentBuilder docSource = jsonBuilder().startObject().startObject("location") + XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") .field("type", "geometrycollection") .startArray("geometries") .startObject() @@ -557,7 +549,7 @@ public void testShapeFilterWithDefinedGeoCollection() throws Exception { .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( - "location", + "geo", new GeometryCollectionBuilder() .polygon( new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) @@ -568,7 +560,7 @@ public void testShapeFilterWithDefinedGeoCollection() throws Exception { assertSearchResponse(result); assertHitCount(result, 1); filter = QueryBuilders.geoShapeQuery( - "location", + "geo", new GeometryCollectionBuilder().polygon( new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) .coordinate(193.0, 13.0).coordinate(193.0, -11.0) @@ -577,7 +569,7 @@ public void testShapeFilterWithDefinedGeoCollection() throws Exception { .setPostFilter(filter).get(); assertSearchResponse(result); assertHitCount(result, 0); - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder() + filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder() .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) .polygon( @@ -589,7 +581,7 @@ public void testShapeFilterWithDefinedGeoCollection() throws Exception { assertSearchResponse(result); assertHitCount(result, 1); // no shape - filter = QueryBuilders.geoShapeQuery("location", new GeometryCollectionBuilder()); + filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder()); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); @@ -598,7 +590,7 @@ public void testShapeFilterWithDefinedGeoCollection() throws Exception { public void testPointsOnly() throws Exception { String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") + .startObject("properties").startObject("geo") .field("type", "geo_shape") .field("tree", randomBoolean() ? "quadtree" : "geohash") .field("tree_levels", "6") @@ -613,7 +605,7 @@ public void testPointsOnly() throws Exception { ShapeBuilder shape = RandomShapeGenerator.createShape(random()); try { client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setSource(jsonBuilder().startObject().field("geo", shape).endObject()) .setRefreshPolicy(IMMEDIATE).get(); } catch (MapperParsingException e) { // RandomShapeGenerator created something other than a POINT type, verify the correct exception is thrown @@ -623,7 +615,7 @@ public void testPointsOnly() throws Exception { // test that point was inserted SearchResponse response = client().prepareSearch("geo_points_only") - .setQuery(geoIntersectionQuery("location", shape)) + .setQuery(geoIntersectionQuery("geo", shape)) .get(); assertEquals(1, response.getHits().getTotalHits().value); @@ -631,7 +623,7 @@ public void testPointsOnly() throws Exception { public void testPointsOnlyExplicit() throws Exception { String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") + .startObject("properties").startObject("geo") .field("type", "geo_shape") .field("tree", randomBoolean() ? "quadtree" : "geohash") .field("tree_levels", "6") @@ -646,13 +638,13 @@ public void testPointsOnlyExplicit() throws Exception { // MULTIPOINT ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); client().prepareIndex("geo_points_only").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setSource(jsonBuilder().startObject().field("geo", shape).endObject()) .setRefreshPolicy(IMMEDIATE).get(); // POINT shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.POINT); client().prepareIndex("geo_points_only").setId("2") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setSource(jsonBuilder().startObject().field("geo", shape).endObject()) .setRefreshPolicy(IMMEDIATE).get(); // test that point was inserted @@ -664,26 +656,25 @@ public void testPointsOnlyExplicit() throws Exception { } public void testFieldAlias() throws IOException { - createIndex("test"); XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties") - .startObject("location") + .startObject("geo") .field("type", "geo_shape") .field("tree", randomBoolean() ? "quadtree" : "geohash") .endObject() .startObject("alias") .field("type", "alias") - .field("path", "location") + .field("path", "geo") .endObject() .endObject() .endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) - .execute().actionGet(); + client().admin().indices().prepareCreate("test").setMapping(xcb.toString()).get(); + ensureGreen(); ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setSource(jsonBuilder().startObject().field("geo", shape).endObject()) .setRefreshPolicy(IMMEDIATE).get(); SearchResponse response = client().prepareSearch("test") @@ -693,16 +684,10 @@ public void testFieldAlias() throws IOException { } // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws IOException { - Settings settings = Settings.builder().put("index.number_of_shards", 1).build(); - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties") - .startObject("geo").field("type", "geo_shape").endObject() - .endObject() - .endObject(); - - client().admin().indices().prepareCreate("test").setSettings(settings).setMapping(xcb.toString()) - .execute().actionGet(); + public void testEnvelopeSpanningDateline() throws Exception { + String mapping = Strings.toString(createRandomMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + "\"type\": \"Point\"\r\n" + "}}"; From 2d880c260540139a356be59d161d99436ac9070a Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 8 Jan 2020 12:11:41 +0100 Subject: [PATCH 11/18] GeoShapeQueryTests.java passing tests --- .../search/geo/GeoShapeQueryTests.java | 116 +++++++++--------- 1 file changed, 60 insertions(+), 56 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 605d17e1c0c7d..91dc0f60180a0 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -90,6 +90,18 @@ private XContentBuilder createMapping() throws Exception { return xcb; } + private XContentBuilder createMapping(String tree) throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("geo") + .field("type", "geo_shape") + .field("tree", tree) + .endObject() + .endObject() + .endObject(); + + return xcb; + } + private XContentBuilder createRandomMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") @@ -103,16 +115,12 @@ private XContentBuilder createRandomMapping() throws Exception { return xcb; } - private XContentBuilder createQuadtreeMapping() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("geo") - .field("type", "geo_shape") - .field("tree", LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE) - .endObject() - .endObject() - .endObject(); + private XContentBuilder createGeohashMapping() throws Exception { + return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH); + } - return xcb; + private XContentBuilder createQuadtreeMapping() throws Exception { + return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE); } public void testIndexPointsFilterRectangle() throws Exception { @@ -267,14 +275,16 @@ private void assertUnmodified(ShapeBuilder builder) throws IOException { public void testShapeFetchingPath() throws Exception { createIndex("shapes"); - String mapping = Strings.toString(createRandomMapping()); + String mapping = Strings.toString(createMapping()); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - String location = "\"location\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; + ensureGreen(); + + String geo = "\"geo\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; client().prepareIndex("shapes").setId("1") .setSource( String.format( - Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", location, location, location, location + Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", geo, geo, geo, geo ), XContentType.JSON) .setRefreshPolicy(IMMEDIATE).get(); client().prepareIndex("test").setId("1") @@ -298,21 +308,21 @@ public void testShapeFetchingPath() throws Exception { assertHitCount(result, 1); filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); + .indexedShapePath("1.geo"); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); assertHitCount(result, 1); filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); + .indexedShapePath("1.2.geo"); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); assertHitCount(result, 1); filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); + .indexedShapePath("1.2.3.geo"); result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) .setPostFilter(filter).get(); assertSearchResponse(result); @@ -327,19 +337,19 @@ public void testShapeFetchingPath() throws Exception { assertHitCount(result, 1); query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") - .indexedShapePath("1.location"); + .indexedShapePath("1.geo"); result = client().prepareSearch("test").setQuery(query).get(); assertSearchResponse(result); assertHitCount(result, 1); query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") - .indexedShapePath("1.2.location"); + .indexedShapePath("1.2.geo"); result = client().prepareSearch("test").setQuery(query).get(); assertSearchResponse(result); assertHitCount(result, 1); query = QueryBuilders.geoShapeQuery("geo", "1") .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.location"); + .indexedShapePath("1.2.3.geo"); result = client().prepareSearch("test").setQuery(query).get(); assertSearchResponse(result); assertHitCount(result, 1); @@ -408,19 +418,22 @@ public void testRandomGeoCollectionQuery() throws Exception { logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), usePrefixTrees ? "default" : "quadtree"); - // don't use random mapping as permits quadtree - String mapping = Strings.toString(usePrefixTrees ? createQuadtreeMapping() : createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + if (usePrefixTrees == false) { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") + .execute().actionGet(); + } else { + client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") + .execute().actionGet(); + } - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); // Create a random geometry collection to query GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); queryCollection.shape(new PolygonBuilder(cb)); - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", queryCollection); + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); assertSearchResponse(result); @@ -514,14 +527,9 @@ public void testExistsQuery() throws Exception { } public void testShapeFilterWithDefinedGeoCollection() throws Exception { - createIndex("shapes"); - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("geo") - .field("type", "geo_shape") - .field("tree", "quadtree") - .endObject().endObject().endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()) - .execute().actionGet(); + String mapping = Strings.toString(createQuadtreeMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") .field("type", "geometrycollection") @@ -656,25 +664,27 @@ public void testPointsOnlyExplicit() throws Exception { } public void testFieldAlias() throws IOException { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() + .startObject("type") .startObject("properties") - .startObject("geo") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "geo") - .endObject() + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() .endObject() - .endObject(); + .endObject(); - client().admin().indices().prepareCreate("test").setMapping(xcb.toString()).get(); + createIndex("test", Settings.EMPTY, "type", mapping); ensureGreen(); ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("geo", shape).endObject()) + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) .setRefreshPolicy(IMMEDIATE).get(); SearchResponse response = client().prepareSearch("test") @@ -685,8 +695,8 @@ public void testFieldAlias() throws IOException { // Test for issue #34418 public void testEnvelopeSpanningDateline() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + XContentBuilder mapping = createMapping(); + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); ensureGreen(); String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + @@ -746,16 +756,10 @@ public void testEnvelopeSpanningDateline() throws Exception { assertNotEquals("1", response.getHits().getAt(1).getId()); } - public void testGeometryCollectionRelations() throws IOException { - Settings settings = Settings.builder().put("index.number_of_shards", 1).build(); - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties") - .startObject("geo").field("type", "geo_shape").endObject() - .endObject() - .endObject(); - - client().admin().indices().prepareCreate("test").setSettings(settings).setMapping(xcb.toString()) - .execute().actionGet(); + public void testGeometryCollectionRelations() throws Exception { + XContentBuilder mapping = createMapping(); + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + ensureGreen(); EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10)); From e275f3eb0a771fd11aa967b4d7653f7f64276a87 Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 8 Jan 2020 12:21:19 +0100 Subject: [PATCH 12/18] GeoShapeQueryTests.java extends GeoQueryTests --- .../org/elasticsearch/search/geo/GeoShapeQueryTests.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 91dc0f60180a0..8370d9a3b8b23 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -73,13 +73,14 @@ import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.nullValue; -public class GeoShapeQueryTests extends ESSingleNodeTestCase { +public class GeoShapeQueryTests extends GeoQueryTests { private static final String[] PREFIX_TREES = new String[] { LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH, LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE }; - private XContentBuilder createMapping() throws Exception { + @Override + protected XContentBuilder createMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") .field("type", "geo_shape") From 316c7b18e843fef85c668aaf3aefdb69d9909b17 Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 8 Jan 2020 12:35:58 +0100 Subject: [PATCH 13/18] refactored + tests passing --- .../org/elasticsearch/search/geo/GeoQueryTests.java | 11 ----------- .../elasticsearch/search/geo/GeoShapeQueryTests.java | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index 0d74479b842aa..8fba89aa49b53 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -79,15 +79,4 @@ public abstract class GeoQueryTests extends ESSingleNodeTestCase { protected abstract XContentBuilder createMapping() throws Exception; - public void testNullShape() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - GetResponse result = client().prepareGet("test", "aNullshape").get(); - assertThat(result.getField("location"), nullValue()); - } - } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 8370d9a3b8b23..c67e2e9c24077 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -124,6 +124,17 @@ private XContentBuilder createQuadtreeMapping() throws Exception { return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE); } + public void testNullShape() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + GetResponse result = client().prepareGet("test", "aNullshape").get(); + assertThat(result.getField("location"), nullValue()); + } + public void testIndexPointsFilterRectangle() throws Exception { String mapping = Strings.toString(createRandomMapping()); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); From e7e5e7b86c853314445938090fc4782fbd58b45e Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 8 Jan 2020 12:43:10 +0100 Subject: [PATCH 14/18] refactored + tests passing --- .../search/geo/GeoPointShapeQueryTests.java | 65 ++++++++++--------- .../search/geo/GeoQueryTests.java | 48 -------------- 2 files changed, 34 insertions(+), 79 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index a740630b30892..0e45f998c262a 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -1,32 +1,49 @@ +/* + * 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.search.geo; -import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.SpatialStrategy; import org.elasticsearch.common.geo.builders.*; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; import org.locationtech.jts.geom.Coordinate; import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.nullValue; -import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; public class GeoPointShapeQueryTests extends GeoQueryTests { + @Override + protected XContentBuilder createMapping() throws Exception { + XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() + .startObject("properties").startObject("location") + .field("type", "geo_point") + .endObject().endObject().endObject(); + + return xcb; + } + public void testIndexPointsFilterRectangle() throws Exception { String mapping = Strings.toString(createMapping()); // where does the mapping ensure geo_shape type for the location field, a template? - client().admin().indices().prepareCreate("test").setMapping(createMapping().toString()).get(); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() @@ -41,34 +58,20 @@ public void testIndexPointsFilterRectangle() throws Exception { EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - // This is deprecated...? go fix + // Pending new query processor for lat lon point queries + new code for geo shape field mapper + + /* SearchResponse searchResponse = client().prepareSearch("test") .setQuery(geoShapeQuery("location", shape)) .get(); assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", shape)) - .get(); - assertSearchResponse(searchResponse); assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); assertThat(searchResponse.getHits().getHits().length, equalTo(1)); assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - @Override - protected XContentBuilder createMapping() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("location") - .field("type", "geo_point") - .endObject().endObject().endObject(); + */ - return xcb; } } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index 8fba89aa49b53..99c9d5bd7c07d 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -19,57 +19,9 @@ package org.elasticsearch.search.geo; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; - -import org.apache.lucene.geo.GeoTestUtil; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.CheckedSupplier; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.common.geo.SpatialStrategy; -import org.elasticsearch.common.geo.builders.CoordinatesBuilder; -import org.elasticsearch.common.geo.builders.EnvelopeBuilder; -import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder; -import org.elasticsearch.common.geo.builders.LineStringBuilder; -import org.elasticsearch.common.geo.builders.MultiPointBuilder; -import org.elasticsearch.common.geo.builders.PointBuilder; -import org.elasticsearch.common.geo.builders.PolygonBuilder; -import org.elasticsearch.common.geo.builders.ShapeBuilder; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.query.ExistsQueryBuilder; -import org.elasticsearch.index.query.GeoShapeQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.test.ESSingleNodeTestCase; -import org.elasticsearch.test.geo.RandomShapeGenerator; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.spatial4j.shape.Rectangle; - -import java.io.IOException; -import java.util.Locale; - -import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; -import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; -import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery; -import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; -import static org.elasticsearch.test.geo.RandomShapeGenerator.createGeometryCollectionWithin; -import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomPoint; -import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.nullValue; public abstract class GeoQueryTests extends ESSingleNodeTestCase { protected static final String[] PREFIX_TREES = new String[] { From d7f2218a3ca3fa0d87e888d68bd6ec5ed1db6afb Mon Sep 17 00:00:00 2001 From: djptek Date: Wed, 8 Jan 2020 12:58:43 +0100 Subject: [PATCH 15/18] reset GeoShapeQueryBuilder.java for future PR --- .../org/elasticsearch/index/query/GeoShapeQueryBuilder.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java index b1c14116c747a..78c727a90212b 100644 --- a/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java @@ -35,7 +35,6 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.geometry.Geometry; import org.elasticsearch.index.mapper.AbstractGeometryFieldMapper; -import org.elasticsearch.index.mapper.GeoPointFieldMapper; import org.elasticsearch.index.mapper.GeoShapeFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; @@ -198,8 +197,7 @@ protected GeoShapeQueryBuilder newShapeQueryBuilder(String fieldName, Supplier Date: Thu, 9 Jan 2020 19:29:03 +0100 Subject: [PATCH 16/18] improved refactoring see: https://github.com/elastic/elasticsearch/pull/50737#pullrequestreview-340443408 --- .../search/geo/GeoPointShapeQueryTests.java | 72 ++- .../search/geo/GeoQueryTests.java | 499 +++++++++++++++++ .../search/geo/GeoShapeQueryTests.java | 525 ++---------------- 3 files changed, 590 insertions(+), 506 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index 0e45f998c262a..5124025334491 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -20,13 +20,10 @@ package org.elasticsearch.search.geo; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.builders.*; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.locationtech.jts.geom.Coordinate; -import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; -import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import java.io.IOException; public class GeoPointShapeQueryTests extends GeoQueryTests { @@ -40,38 +37,57 @@ protected XContentBuilder createMapping() throws Exception { return xcb; } - public void testIndexPointsFilterRectangle() throws Exception { - String mapping = Strings.toString(createMapping()); - // where does the mapping ensure geo_shape type for the location field, a template? - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + public void testNullShape() throws Exception { + super.testNullShape(); + } - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startArray("location").value(-30).value(-30).endArray() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); + public void testIndexPointsFilterRectangle() throws Exception { + //super.testIndexPointsFilterRectangle(Strings.toString(createMapping())); + } + public void testIndexedShapeReference() throws Exception { + //super.testIndexedShapeReference(Strings.toString(createMapping())); + } - client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() - .field("name", "Document 2") - .startArray("location").value(-45).value(-50).endArray() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); + public void testShapeFetchingPath() throws Exception { + //super.testShapeFetchingPath(); + } - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + public void testQueryRandomGeoCollection() throws Exception { + //super.testQueryRandomGeoCollection(Strings.toString(createMapping())); + } - // Pending new query processor for lat lon point queries + new code for geo shape field mapper + public void testRandomGeoCollectionQuery() throws Exception { + //super.testRandomGeoCollectionQuery(); + } - /* - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("location", shape)) - .get(); + public void testShapeFilterWithDefinedGeoCollection() throws Exception { + //super.testShapeFilterWithDefinedGeoCollection(Strings.toString(createMapping())); + } - assertSearchResponse(searchResponse); + public void testFieldAlias() throws IOException { + /* super.testFieldAlias(XContentFactory.jsonBuilder() + .startObject() + .startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_point") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() + .endObject() + .endObject()); */ + } - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - */ + // Test for issue #34418 + public void testEnvelopeSpanningDateline() throws Exception { + //super.testEnvelopeSpanningDateline(); + } + public void testGeometryCollectionRelations() throws Exception { + //super.testGeometryCollectionRelations(); } } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index 99c9d5bd7c07d..806114d8d8f89 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -19,9 +19,39 @@ package org.elasticsearch.search.geo; +import com.carrotsearch.randomizedtesting.generators.RandomNumbers; +import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.geo.ShapeRelation; +import org.elasticsearch.common.geo.builders.*; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.query.GeoShapeQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.test.ESSingleNodeTestCase; +import org.elasticsearch.test.geo.RandomShapeGenerator; +import org.locationtech.jts.geom.Coordinate; + +import java.io.IOException; +import java.util.Locale; + +import static org.apache.lucene.util.LuceneTestCase.random; +import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public abstract class GeoQueryTests extends ESSingleNodeTestCase { protected static final String[] PREFIX_TREES = new String[] { @@ -31,4 +61,473 @@ public abstract class GeoQueryTests extends ESSingleNodeTestCase { protected abstract XContentBuilder createMapping() throws Exception; + //protected abstract XContentBuilder createRandomMapping() throws Exception; + + public void testNullShape() throws Exception { + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + client().prepareIndex("test").setId("aNullshape").setSource("{\"geo\": null}", XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + GetResponse result = client().prepareGet("test", "aNullshape").get(); + assertThat(result.getField("location"), nullValue()); + }; + + public void testIndexPointsFilterRectangle(String mapping) throws Exception { + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("geo") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() + .field("name", "Document 2") + .startObject("geo") + .field("type", "point") + .startArray("coordinates").value(-45).value(-50).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("geo", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", shape)) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testIndexedShapeReference(String mapping) throws Exception { + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + createIndex("shapes"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("geo") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("geo", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testShapeFetchingPath() throws Exception { + createIndex("shapes"); + String mapping = Strings.toString(createMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + String geo = "\"geo\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; + + client().prepareIndex("shapes").setId("1") + .setSource( + String.format( + Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", geo, geo, geo, geo + ), XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().startObject("geo") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-20).value(-20).endArray() + .startArray().value(20).value(-20).endArray() + .startArray().value(20).value(20).endArray() + .startArray().value(-20).value(20).endArray() + .startArray().value(-20).value(-20).endArray() + .endArray().endArray() + .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("geo"); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.geo"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.geo"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.geo"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + + // now test the query variant + GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } + + public void testFieldAlias(XContentBuilder mapping) throws IOException { + createIndex("test", Settings.EMPTY, "type", mapping); + ensureGreen(); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("alias", shape)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } + + // TBC whether the following tests will be applicable to geo_point + public void testQueryRandomGeoCollection(String mapping) throws Exception { + // Create a random geometry collection. + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assumeTrue("Skipping the check for the polygon with a degenerated dimension until " + +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + assertHitCount(result, 1); + } + + 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); + } + } + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + + assumeTrue("Skipping the check for the polygon with a degenerated dimension", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), + usePrefixTrees ? "default" : "quadtree"); + + client().admin().indices() + .prepareCreate("test") + .addMapping("type", "location", usePrefixTrees ? "type=geo_shape" : "type=geo_shape,tree=quadtree") + .execute().actionGet(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // Create a random geometry collection to query + GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); + queryCollection.shape(new PolygonBuilder(cb)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), + result.getHits().getTotalHits().value > 0); + } + + public void testShapeFilterWithDefinedGeoCollection(String mapping) throws Exception { + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") + .field("type", "geometrycollection") + .startArray("geometries") + .startObject() + .field("type", "point") + .startArray("coordinates") + .value(100.0).value(0.0) + .endArray() + .endObject() + .startObject() + .field("type", "linestring") + .startArray("coordinates") + .startArray() + .value(101.0).value(0.0) + .endArray() + .startArray() + .value(102.0).value(1.0) + .endArray() + .endArray() + .endObject() + .endArray() + .endObject().endObject(); + client().prepareIndex("test").setId("1") + .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( + "geo", + new GeometryCollectionBuilder() + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) + .coordinate(103.0, 3.0).coordinate(103.0, -1.0) + .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery( + "geo", + new GeometryCollectionBuilder().polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder() + .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) + .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + // no shape + filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder()); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + } + + // Test for issue #34418 + public void testEnvelopeSpanningDateline() throws Exception { + XContentBuilder mapping = createMapping(); + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + ensureGreen(); + + String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( + () -> QueryBuilders.geoShapeQuery( + "geo", + new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) + ).relation(ShapeRelation.WITHIN), + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .startObject("shape") + .field("type", "envelope") + .startArray("coordinates") + .startArray().value(-21).value(44).endArray() + .startArray().value(-39).value(9).endArray() + .endArray() + .endObject() + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + }, + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .field("shape", "BBOX (-21, -39, 44, 9)") + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + } + ); + + SearchResponse response = client().prepareSearch("test") + .setQuery(querySupplier.get()) + .get(); + assertEquals(2, response.getHits().getTotalHits().value); + assertNotEquals("1", response.getHits().getAt(0).getId()); + assertNotEquals("1", response.getHits().getAt(1).getId()); + } + + public void testGeometryCollectionRelations() throws Exception { + XContentBuilder mapping = createMapping(); + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + ensureGreen(); + + EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10)); + + client().index(new IndexRequest("test") + .source(jsonBuilder().startObject().field("geo", envelopeBuilder).endObject()) + .setRefreshPolicy(IMMEDIATE)).actionGet(); + + { + // A geometry collection that is fully within the indexed shape + GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); + builder.shape(new PointBuilder(1, 2)); + builder.shape(new PointBuilder(-2, -1)); + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + } + // A geometry collection that is partially within the indexed shape + { + GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); + builder.shape(new PointBuilder(1, 2)); + builder.shape(new PointBuilder(20, 30)); + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + } + { + // A geometry collection that is disjoint with the indexed shape + GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); + builder.shape(new PointBuilder(-20, -30)); + builder.shape(new PointBuilder(20, 30)); + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } + } + } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index c67e2e9c24077..796a82b41a92e 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -91,7 +91,7 @@ protected XContentBuilder createMapping() throws Exception { return xcb; } - private XContentBuilder createMapping(String tree) throws Exception { + protected XContentBuilder createMapping(String tree) throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") .field("type", "geo_shape") @@ -103,7 +103,7 @@ private XContentBuilder createMapping(String tree) throws Exception { return xcb; } - private XContentBuilder createRandomMapping() throws Exception { + protected XContentBuilder createRandomMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") .field("type", "geo_shape"); @@ -116,65 +116,68 @@ private XContentBuilder createRandomMapping() throws Exception { return xcb; } - private XContentBuilder createGeohashMapping() throws Exception { + protected XContentBuilder createGeohashMapping() throws Exception { return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH); } - private XContentBuilder createQuadtreeMapping() throws Exception { + protected XContentBuilder createQuadtreeMapping() throws Exception { return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE); } public void testNullShape() throws Exception { - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - client().prepareIndex("test").setId("aNullshape").setSource("{\"location\": null}", XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - GetResponse result = client().prepareGet("test", "aNullshape").get(); - assertThat(result.getField("location"), nullValue()); + super.testNullShape(); } public void testIndexPointsFilterRectangle() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + super.testIndexPointsFilterRectangle(Strings.toString(createRandomMapping())); + } - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("geo") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); + public void testIndexedShapeReference() throws Exception { + super.testIndexedShapeReference(Strings.toString(createRandomMapping())); + } - client().prepareIndex("test").setId("2").setSource(jsonBuilder().startObject() - .field("name", "Document 2") - .startObject("geo") - .field("type", "point") - .startArray("coordinates").value(-45).value(-50).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); + public void testShapeFetchingPath() throws Exception { + super.testShapeFetchingPath(); + } - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + public void testQueryRandomGeoCollection() throws Exception { + super.testQueryRandomGeoCollection( + Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping())); + } - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("geo", shape)) - .get(); + public void testRandomGeoCollectionQuery() throws Exception { + super.testRandomGeoCollectionQuery(); + } - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + public void testShapeFilterWithDefinedGeoCollection() throws Exception { + super.testShapeFilterWithDefinedGeoCollection(Strings.toString(createQuadtreeMapping())); + } - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", shape)) - .get(); + public void testFieldAlias() throws IOException { + super.testFieldAlias(XContentFactory.jsonBuilder() + .startObject() + .startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() + .endObject() + .endObject()); + } - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + // Test for issue #34418 + public void testEnvelopeSpanningDateline() throws Exception { + super.testEnvelopeSpanningDateline(); + } + + public void testGeometryCollectionRelations() throws Exception { + super.testGeometryCollectionRelations(); } public void testEdgeCases() throws Exception { @@ -213,43 +216,6 @@ public void testEdgeCases() throws Exception { assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("blakely")); } - public void testIndexedShapeReference() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - createIndex("shapes"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("geo") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("geo", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - public void testIndexedShapeReferenceSourceDisabled() throws Exception { String mapping = Strings.toString(createRandomMapping()); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); @@ -285,174 +251,6 @@ private void assertUnmodified(ShapeBuilder builder) throws IOException { assertThat(before, equalTo(after)); } - public void testShapeFetchingPath() throws Exception { - createIndex("shapes"); - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - String geo = "\"geo\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; - - client().prepareIndex("shapes").setId("1") - .setSource( - String.format( - Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", geo, geo, geo, geo - ), XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().startObject("geo") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-20).value(-20).endArray() - .startArray().value(20).value(-20).endArray() - .startArray().value(20).value(20).endArray() - .startArray().value(-20).value(20).endArray() - .startArray().value(-20).value(-20).endArray() - .endArray().endArray() - .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("geo"); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.geo"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.geo"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.geo"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - - // now test the query variant - GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testQueryRandomGeoCollection() throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - String mapping = Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assumeTrue("Skipping the check for the polygon with a degenerated dimension until " - +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - assertHitCount(result, 1); - } - - 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); - } - } - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - - assumeTrue("Skipping the check for the polygon with a degenerated dimension", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), - usePrefixTrees ? "default" : "quadtree"); - - if (usePrefixTrees == false) { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape") - .execute().actionGet(); - } else { - client().admin().indices().prepareCreate("test").addMapping("type", "location", "type=geo_shape,tree=quadtree") - .execute().actionGet(); - } - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // Create a random geometry collection to query - GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); - queryCollection.shape(new PolygonBuilder(cb)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), - result.getHits().getTotalHits().value > 0); - } - /** tests querying a random geometry collection with a point */ public void testPointQuery() throws Exception { // Create a random geometry collection to index. @@ -538,76 +336,6 @@ public void testExistsQuery() throws Exception { assertHitCount(result, 1); } - public void testShapeFilterWithDefinedGeoCollection() throws Exception { - String mapping = Strings.toString(createQuadtreeMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") - .field("type", "geometrycollection") - .startArray("geometries") - .startObject() - .field("type", "point") - .startArray("coordinates") - .value(100.0).value(0.0) - .endArray() - .endObject() - .startObject() - .field("type", "linestring") - .startArray("coordinates") - .startArray() - .value(101.0).value(0.0) - .endArray() - .startArray() - .value(102.0).value(1.0) - .endArray() - .endArray() - .endObject() - .endArray() - .endObject().endObject(); - client().prepareIndex("test").setId("1") - .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( - "geo", - new GeometryCollectionBuilder() - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) - .coordinate(103.0, 3.0).coordinate(103.0, -1.0) - .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery( - "geo", - new GeometryCollectionBuilder().polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder() - .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) - .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - // no shape - filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder()); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - } - public void testPointsOnly() throws Exception { String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") @@ -675,163 +403,4 @@ public void testPointsOnlyExplicit() throws Exception { assertEquals(2, response.getHits().getTotalHits().value); } - public void testFieldAlias() throws IOException { - XContentBuilder mapping = XContentFactory.jsonBuilder().startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() - .endObject() - .endObject() - .endObject(); - - createIndex("test", Settings.EMPTY, "type", mapping); - ensureGreen(); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("alias", shape)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - - // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws Exception { - XContentBuilder mapping = createMapping(); - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - ensureGreen(); - - String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( - () -> QueryBuilders.geoShapeQuery( - "geo", - new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) - ).relation(ShapeRelation.WITHIN), - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .startObject("shape") - .field("type", "envelope") - .startArray("coordinates") - .startArray().value(-21).value(44).endArray() - .startArray().value(-39).value(9).endArray() - .endArray() - .endObject() - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - }, - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .field("shape", "BBOX (-21, -39, 44, 9)") - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - } - ); - - SearchResponse response = client().prepareSearch("test") - .setQuery(querySupplier.get()) - .get(); - assertEquals(2, response.getHits().getTotalHits().value); - assertNotEquals("1", response.getHits().getAt(0).getId()); - assertNotEquals("1", response.getHits().getAt(1).getId()); - } - - public void testGeometryCollectionRelations() throws Exception { - XContentBuilder mapping = createMapping(); - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - ensureGreen(); - - EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10)); - - client().index(new IndexRequest("test") - .source(jsonBuilder().startObject().field("geo", envelopeBuilder).endObject()) - .setRefreshPolicy(IMMEDIATE)).actionGet(); - - { - // A geometry collection that is fully within the indexed shape - GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); - builder.shape(new PointBuilder(1, 2)); - builder.shape(new PointBuilder(-2, -1)); - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - } - // A geometry collection that is partially within the indexed shape - { - GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); - builder.shape(new PointBuilder(1, 2)); - builder.shape(new PointBuilder(20, 30)); - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - } - { - // A geometry collection that is disjoint with the indexed shape - GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); - builder.shape(new PointBuilder(-20, -30)); - builder.shape(new PointBuilder(20, 30)); - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - } } From 9025578d4fb3b94aefb2b37671e699abff1df3f8 Mon Sep 17 00:00:00 2001 From: djptek Date: Tue, 14 Jan 2020 15:03:34 +0100 Subject: [PATCH 17/18] refactor --- .../search/geo/GeoPointShapeQueryTests.java | 56 +-- .../search/geo/GeoQueryTests.java | 443 +--------------- .../search/geo/GeoShapeQueryTests.java | 476 ++++++++++++++++-- 3 files changed, 428 insertions(+), 547 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java index 5124025334491..51702c6d08c6c 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoPointShapeQueryTests.java @@ -19,16 +19,13 @@ package org.elasticsearch.search.geo; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import java.io.IOException; - public class GeoPointShapeQueryTests extends GeoQueryTests { @Override - protected XContentBuilder createMapping() throws Exception { + protected XContentBuilder createDefaultMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("location") .field("type", "geo_point") @@ -37,57 +34,8 @@ protected XContentBuilder createMapping() throws Exception { return xcb; } - public void testNullShape() throws Exception { - super.testNullShape(); - } - public void testIndexPointsFilterRectangle() throws Exception { - //super.testIndexPointsFilterRectangle(Strings.toString(createMapping())); - } - public void testIndexedShapeReference() throws Exception { - //super.testIndexedShapeReference(Strings.toString(createMapping())); - } - - public void testShapeFetchingPath() throws Exception { - //super.testShapeFetchingPath(); - } - - public void testQueryRandomGeoCollection() throws Exception { - //super.testQueryRandomGeoCollection(Strings.toString(createMapping())); - } - - public void testRandomGeoCollectionQuery() throws Exception { - //super.testRandomGeoCollectionQuery(); - } - - public void testShapeFilterWithDefinedGeoCollection() throws Exception { - //super.testShapeFilterWithDefinedGeoCollection(Strings.toString(createMapping())); - } - - public void testFieldAlias() throws IOException { - /* super.testFieldAlias(XContentFactory.jsonBuilder() - .startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_point") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() - .endObject() - .endObject() - .endObject()); */ - } - - // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws Exception { - //super.testEnvelopeSpanningDateline(); - } - - public void testGeometryCollectionRelations() throws Exception { - //super.testGeometryCollectionRelations(); + //super.testIndexPointsFilterRectangle(Strings.toString(createDefaultMapping())); } } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index 806114d8d8f89..91b27fb4e3579 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -19,52 +19,28 @@ package org.elasticsearch.search.geo; -import com.carrotsearch.randomizedtesting.generators.RandomNumbers; -import org.apache.lucene.geo.GeoTestUtil; import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.builders.*; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.query.GeoShapeQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.test.ESSingleNodeTestCase; -import org.elasticsearch.test.geo.RandomShapeGenerator; import org.locationtech.jts.geom.Coordinate; -import java.io.IOException; -import java.util.Locale; - -import static org.apache.lucene.util.LuceneTestCase.random; import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.*; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; public abstract class GeoQueryTests extends ESSingleNodeTestCase { - protected static final String[] PREFIX_TREES = new String[] { - LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH, - LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE - }; - - protected abstract XContentBuilder createMapping() throws Exception; - //protected abstract XContentBuilder createRandomMapping() throws Exception; + protected abstract XContentBuilder createDefaultMapping() throws Exception; public void testNullShape() throws Exception { - String mapping = Strings.toString(createMapping()); + String mapping = Strings.toString(createDefaultMapping()); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); @@ -115,419 +91,4 @@ public void testIndexPointsFilterRectangle(String mapping) throws Exception { assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); } - public void testIndexedShapeReference(String mapping) throws Exception { - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - createIndex("shapes"); - ensureGreen(); - - EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); - - client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() - .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() - .field("name", "Document 1") - .startObject("geo") - .field("type", "point") - .startArray("coordinates").value(-30).value(-30).endArray() - .endObject() - .endObject()).setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(geoIntersectionQuery("geo", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - - searchResponse = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", "Big_Rectangle")) - .get(); - - assertSearchResponse(searchResponse); - assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); - assertThat(searchResponse.getHits().getHits().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); - } - - public void testShapeFetchingPath() throws Exception { - createIndex("shapes"); - String mapping = Strings.toString(createMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - String geo = "\"geo\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; - - client().prepareIndex("shapes").setId("1") - .setSource( - String.format( - Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", geo, geo, geo, geo - ), XContentType.JSON) - .setRefreshPolicy(IMMEDIATE).get(); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().startObject("geo") - .field("type", "polygon") - .startArray("coordinates").startArray() - .startArray().value(-20).value(-20).endArray() - .startArray().value(20).value(-20).endArray() - .startArray().value(20).value(20).endArray() - .startArray().value(-20).value(20).endArray() - .startArray().value(-20).value(-20).endArray() - .endArray().endArray() - .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("geo"); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.geo"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.geo"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.geo"); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - - // now test the query variant - GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - query = QueryBuilders.geoShapeQuery("geo", "1") - .indexedShapeIndex("shapes") - .indexedShapePath("1.2.3.geo"); - result = client().prepareSearch("test").setQuery(query).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - } - - public void testFieldAlias(XContentBuilder mapping) throws IOException { - createIndex("test", Settings.EMPTY, "type", mapping); - ensureGreen(); - - ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); - client().prepareIndex("test").setId("1") - .setSource(jsonBuilder().startObject().field("location", shape).endObject()) - .setRefreshPolicy(IMMEDIATE).get(); - - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("alias", shape)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - - // TBC whether the following tests will be applicable to geo_point - public void testQueryRandomGeoCollection(String mapping) throws Exception { - // Create a random geometry collection. - GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assumeTrue("Skipping the check for the polygon with a degenerated dimension until " - +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - assertHitCount(result, 1); - } - - 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); - } - } - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - - assumeTrue("Skipping the check for the polygon with a degenerated dimension", - randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - - CoordinatesBuilder cb = new CoordinatesBuilder(); - for (int i = 0; i < randomPoly.numPoints(); ++i) { - cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); - } - gcb.shape(new PolygonBuilder(cb)); - - logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), - usePrefixTrees ? "default" : "quadtree"); - - client().admin().indices() - .prepareCreate("test") - .addMapping("type", "location", usePrefixTrees ? "type=geo_shape" : "type=geo_shape,tree=quadtree") - .execute().actionGet(); - - XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); - client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - // Create a random geometry collection to query - GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); - queryCollection.shape(new PolygonBuilder(cb)); - - GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); - geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); - assertSearchResponse(result); - assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), - result.getHits().getTotalHits().value > 0); - } - - public void testShapeFilterWithDefinedGeoCollection(String mapping) throws Exception { - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); - - XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") - .field("type", "geometrycollection") - .startArray("geometries") - .startObject() - .field("type", "point") - .startArray("coordinates") - .value(100.0).value(0.0) - .endArray() - .endObject() - .startObject() - .field("type", "linestring") - .startArray("coordinates") - .startArray() - .value(101.0).value(0.0) - .endArray() - .startArray() - .value(102.0).value(1.0) - .endArray() - .endArray() - .endObject() - .endArray() - .endObject().endObject(); - client().prepareIndex("test").setId("1") - .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); - - GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( - "geo", - new GeometryCollectionBuilder() - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) - .coordinate(103.0, 3.0).coordinate(103.0, -1.0) - .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); - SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - filter = QueryBuilders.geoShapeQuery( - "geo", - new GeometryCollectionBuilder().polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder() - .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) - .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) - .polygon( - new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) - .coordinate(193.0, 13.0).coordinate(193.0, -11.0) - .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 1); - // no shape - filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder()); - result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) - .setPostFilter(filter).get(); - assertSearchResponse(result); - assertHitCount(result, 0); - } - - // Test for issue #34418 - public void testEnvelopeSpanningDateline() throws Exception { - XContentBuilder mapping = createMapping(); - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - ensureGreen(); - - String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + - "\"type\": \"Point\"\r\n" + "}}"; - client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); - - @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( - () -> QueryBuilders.geoShapeQuery( - "geo", - new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) - ).relation(ShapeRelation.WITHIN), - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .startObject("shape") - .field("type", "envelope") - .startArray("coordinates") - .startArray().value(-21).value(44).endArray() - .startArray().value(-39).value(9).endArray() - .endArray() - .endObject() - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - }, - () -> { - XContentBuilder builder = XContentFactory.jsonBuilder().startObject() - .startObject("geo") - .field("shape", "BBOX (-21, -39, 44, 9)") - .field("relation", "within") - .endObject() - .endObject(); - try (XContentParser parser = createParser(builder)){ - parser.nextToken(); - return GeoShapeQueryBuilder.fromXContent(parser); - } - } - ); - - SearchResponse response = client().prepareSearch("test") - .setQuery(querySupplier.get()) - .get(); - assertEquals(2, response.getHits().getTotalHits().value); - assertNotEquals("1", response.getHits().getAt(0).getId()); - assertNotEquals("1", response.getHits().getAt(1).getId()); - } - - public void testGeometryCollectionRelations() throws Exception { - XContentBuilder mapping = createMapping(); - createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); - ensureGreen(); - - EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10)); - - client().index(new IndexRequest("test") - .source(jsonBuilder().startObject().field("geo", envelopeBuilder).endObject()) - .setRefreshPolicy(IMMEDIATE)).actionGet(); - - { - // A geometry collection that is fully within the indexed shape - GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); - builder.shape(new PointBuilder(1, 2)); - builder.shape(new PointBuilder(-2, -1)); - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - } - // A geometry collection that is partially within the indexed shape - { - GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); - builder.shape(new PointBuilder(1, 2)); - builder.shape(new PointBuilder(20, 30)); - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - } - { - // A geometry collection that is disjoint with the indexed shape - GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); - builder.shape(new PointBuilder(-20, -30)); - builder.shape(new PointBuilder(20, 30)); - SearchResponse response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) - .get(); - assertEquals(0, response.getHits().getTotalHits().value); - response = client().prepareSearch("test") - .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) - .get(); - assertEquals(1, response.getHits().getTotalHits().value); - } - } - } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 796a82b41a92e..75424d52b0a73 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -22,7 +22,6 @@ import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import org.apache.lucene.geo.GeoTestUtil; -import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.CheckedSupplier; @@ -47,7 +46,6 @@ import org.elasticsearch.index.query.ExistsQueryBuilder; import org.elasticsearch.index.query.GeoShapeQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.geo.RandomShapeGenerator; import org.locationtech.jts.geom.Coordinate; import org.locationtech.spatial4j.shape.Rectangle; @@ -74,13 +72,13 @@ import static org.hamcrest.Matchers.nullValue; public class GeoShapeQueryTests extends GeoQueryTests { - private static final String[] PREFIX_TREES = new String[] { + protected static final String[] PREFIX_TREES = new String[] { LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH, LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE }; @Override - protected XContentBuilder createMapping() throws Exception { + protected XContentBuilder createDefaultMapping() throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") .field("type", "geo_shape") @@ -91,7 +89,7 @@ protected XContentBuilder createMapping() throws Exception { return xcb; } - protected XContentBuilder createMapping(String tree) throws Exception { + protected XContentBuilder createPrefixTreeMapping(String tree) throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") .field("type", "geo_shape") @@ -116,68 +114,272 @@ protected XContentBuilder createRandomMapping() throws Exception { return xcb; } - protected XContentBuilder createGeohashMapping() throws Exception { - return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.GEOHASH); - } - - protected XContentBuilder createQuadtreeMapping() throws Exception { - return createMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE); - } - - public void testNullShape() throws Exception { - super.testNullShape(); - } - public void testIndexPointsFilterRectangle() throws Exception { super.testIndexPointsFilterRectangle(Strings.toString(createRandomMapping())); } - public void testIndexedShapeReference() throws Exception { - super.testIndexedShapeReference(Strings.toString(createRandomMapping())); - } - public void testShapeFetchingPath() throws Exception { - super.testShapeFetchingPath(); - } + createIndex("shapes"); + String mapping = Strings.toString(createDefaultMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); - public void testQueryRandomGeoCollection() throws Exception { - super.testQueryRandomGeoCollection( - Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping())); + String geo = "\"geo\" : {\"type\":\"polygon\", \"coordinates\":[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]}"; + + client().prepareIndex("shapes").setId("1") + .setSource( + String.format( + Locale.ROOT, "{ %s, \"1\" : { %s, \"2\" : { %s, \"3\" : { %s } }} }", geo, geo, geo, geo + ), XContentType.JSON) + .setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().startObject("geo") + .field("type", "polygon") + .startArray("coordinates").startArray() + .startArray().value(-20).value(-20).endArray() + .startArray().value(20).value(-20).endArray() + .startArray().value(20).value(20).endArray() + .startArray().value(-20).value(20).endArray() + .startArray().value(-20).value(-20).endArray() + .endArray().endArray() + .endObject().endObject()).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("geo"); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.geo"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.geo"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery("geo", "1").relation(ShapeRelation.INTERSECTS) + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.geo"); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + + // now test the query variant + GeoShapeQueryBuilder query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + query = QueryBuilders.geoShapeQuery("geo", "1") + .indexedShapeIndex("shapes") + .indexedShapePath("1.2.3.geo"); + result = client().prepareSearch("test").setQuery(query).get(); + assertSearchResponse(result); + assertHitCount(result, 1); } public void testRandomGeoCollectionQuery() throws Exception { - super.testRandomGeoCollectionQuery(); - } + 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); + } + } + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); - public void testShapeFilterWithDefinedGeoCollection() throws Exception { - super.testShapeFilterWithDefinedGeoCollection(Strings.toString(createQuadtreeMapping())); - } + assumeTrue("Skipping the check for the polygon with a degenerated dimension", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); - public void testFieldAlias() throws IOException { - super.testFieldAlias(XContentFactory.jsonBuilder() - .startObject() - .startObject("type") - .startObject("properties") - .startObject("location") - .field("type", "geo_shape") - .field("tree", randomBoolean() ? "quadtree" : "geohash") - .endObject() - .startObject("alias") - .field("type", "alias") - .field("path", "location") - .endObject() - .endObject() - .endObject() - .endObject()); + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes using {} tree", gcb.numShapes(), + usePrefixTrees ? "default" : "quadtree"); + + client().admin().indices() + .prepareCreate("test") + .addMapping("type", "location", usePrefixTrees ? "type=geo_shape" : "type=geo_shape,tree=quadtree") + .execute().actionGet(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("location"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + // Create a random geometry collection to query + GeometryCollectionBuilder queryCollection = RandomShapeGenerator.createGeometryCollection(random()); + queryCollection.shape(new PolygonBuilder(cb)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("location", queryCollection); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertTrue("query: " + geoShapeQueryBuilder.toString() + " doc: " + Strings.toString(docSource), + result.getHits().getTotalHits().value > 0); } // Test for issue #34418 public void testEnvelopeSpanningDateline() throws Exception { - super.testEnvelopeSpanningDateline(); + XContentBuilder mapping = createDefaultMapping(); + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + ensureGreen(); + + String doc1 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-33.918711,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("1").source(doc1, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc2 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "-49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("2").source(doc2, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + String doc3 = "{\"geo\": {\r\n" + "\"coordinates\": [\r\n" + "49.0,\r\n" + "18.847685\r\n" + "],\r\n" + + "\"type\": \"Point\"\r\n" + "}}"; + client().index(new IndexRequest("test").id("3").source(doc3, XContentType.JSON).setRefreshPolicy(IMMEDIATE)).actionGet(); + + @SuppressWarnings("unchecked") CheckedSupplier querySupplier = randomFrom( + () -> QueryBuilders.geoShapeQuery( + "geo", + new EnvelopeBuilder(new Coordinate(-21, 44), new Coordinate(-39, 9)) + ).relation(ShapeRelation.WITHIN), + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .startObject("shape") + .field("type", "envelope") + .startArray("coordinates") + .startArray().value(-21).value(44).endArray() + .startArray().value(-39).value(9).endArray() + .endArray() + .endObject() + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + }, + () -> { + XContentBuilder builder = XContentFactory.jsonBuilder().startObject() + .startObject("geo") + .field("shape", "BBOX (-21, -39, 44, 9)") + .field("relation", "within") + .endObject() + .endObject(); + try (XContentParser parser = createParser(builder)){ + parser.nextToken(); + return GeoShapeQueryBuilder.fromXContent(parser); + } + } + ); + + SearchResponse response = client().prepareSearch("test") + .setQuery(querySupplier.get()) + .get(); + assertEquals(2, response.getHits().getTotalHits().value); + assertNotEquals("1", response.getHits().getAt(0).getId()); + assertNotEquals("1", response.getHits().getAt(1).getId()); } public void testGeometryCollectionRelations() throws Exception { - super.testGeometryCollectionRelations(); + XContentBuilder mapping = createDefaultMapping(); + createIndex("test", Settings.builder().put("index.number_of_shards", 1).build(), "doc", mapping); + ensureGreen(); + + EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(-10, 10), new Coordinate(10, -10)); + + client().index(new IndexRequest("test") + .source(jsonBuilder().startObject().field("geo", envelopeBuilder).endObject()) + .setRefreshPolicy(IMMEDIATE)).actionGet(); + + { + // A geometry collection that is fully within the indexed shape + GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); + builder.shape(new PointBuilder(1, 2)); + builder.shape(new PointBuilder(-2, -1)); + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + } + // A geometry collection that is partially within the indexed shape + { + GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); + builder.shape(new PointBuilder(1, 2)); + builder.shape(new PointBuilder(20, 30)); + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + } + { + // A geometry collection that is disjoint with the indexed shape + GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); + builder.shape(new PointBuilder(-20, -30)); + builder.shape(new PointBuilder(20, 30)); + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.CONTAINS)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.INTERSECTS)) + .get(); + assertEquals(0, response.getHits().getTotalHits().value); + response = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", builder.buildGeometry()).relation(ShapeRelation.DISJOINT)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } } public void testEdgeCases() throws Exception { @@ -260,7 +462,7 @@ public void testPointQuery() throws Exception { gcb.shape(pb); // don't use random as permits quadtree - String mapping = Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping()); + String mapping = Strings.toString(randomBoolean() ? createDefaultMapping() : createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); @@ -295,7 +497,7 @@ public void testContainsShapeQuery() throws Exception { } // don't use random mapping as permits quadtree - String mapping = Strings.toString(usePrefixTrees ? createQuadtreeMapping() : createMapping()); + String mapping = Strings.toString(usePrefixTrees ? createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE) : createDefaultMapping()); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); @@ -323,7 +525,7 @@ public void testExistsQuery() throws Exception { GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - String mapping = Strings.toString(randomBoolean() ? createMapping() : createQuadtreeMapping()); + String mapping = Strings.toString(randomBoolean() ? createDefaultMapping() : createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); @@ -403,4 +605,174 @@ public void testPointsOnlyExplicit() throws Exception { assertEquals(2, response.getHits().getTotalHits().value); } + public void testIndexedShapeReference() throws Exception { + String mapping = Strings.toString(createRandomMapping()); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + createIndex("shapes"); + ensureGreen(); + + EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); + + client().prepareIndex("shapes").setId("Big_Rectangle").setSource(jsonBuilder().startObject() + .field("shape", shape).endObject()).setRefreshPolicy(IMMEDIATE).get(); + client().prepareIndex("test").setId("1").setSource(jsonBuilder().startObject() + .field("name", "Document 1") + .startObject("geo") + .field("type", "point") + .startArray("coordinates").value(-30).value(-30).endArray() + .endObject() + .endObject()).setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse searchResponse = client().prepareSearch("test") + .setQuery(geoIntersectionQuery("geo", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + + searchResponse = client().prepareSearch("test") + .setQuery(geoShapeQuery("geo", "Big_Rectangle")) + .get(); + + assertSearchResponse(searchResponse); + assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); + assertThat(searchResponse.getHits().getHits().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getId(), equalTo("1")); + } + + public void testFieldAlias() throws IOException { + XContentBuilder mapping = XContentFactory.jsonBuilder() + .startObject() + .startObject("type") + .startObject("properties") + .startObject("location") + .field("type", "geo_shape") + .field("tree", randomBoolean() ? "quadtree" : "geohash") + .endObject() + .startObject("alias") + .field("type", "alias") + .field("path", "location") + .endObject() + .endObject() + .endObject() + .endObject(); + createIndex("test", Settings.EMPTY, "type", mapping); + ensureGreen(); + + ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); + client().prepareIndex("test").setId("1") + .setSource(jsonBuilder().startObject().field("location", shape).endObject()) + .setRefreshPolicy(IMMEDIATE).get(); + + SearchResponse response = client().prepareSearch("test") + .setQuery(geoShapeQuery("alias", shape)) + .get(); + assertEquals(1, response.getHits().getTotalHits().value); + } + + // TBC whether the following tests will be applicable to geo_point + public void testQueryRandomGeoCollection() throws Exception { + // Create a random geometry collection. + String mapping = Strings.toString(randomBoolean() ? createDefaultMapping() : createPrefixTreeMapping( + LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); + GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); + org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); + CoordinatesBuilder cb = new CoordinatesBuilder(); + for (int i = 0; i < randomPoly.numPoints(); ++i) { + cb.coordinate(randomPoly.getPolyLon(i), randomPoly.getPolyLat(i)); + } + gcb.shape(new PolygonBuilder(cb)); + + logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); + + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = (gcb.getShapeAt(gcb.numShapes() - 1)); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assumeTrue("Skipping the check for the polygon with a degenerated dimension until " + +" https://issues.apache.org/jira/browse/LUCENE-8634 is fixed", + randomPoly.maxLat - randomPoly.minLat > 8.4e-8 && randomPoly.maxLon - randomPoly.minLon > 8.4e-8); + assertHitCount(result, 1); + } + + public void testShapeFilterWithDefinedGeoCollection() throws Exception { + String mapping = Strings.toString( + createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") + .field("type", "geometrycollection") + .startArray("geometries") + .startObject() + .field("type", "point") + .startArray("coordinates") + .value(100.0).value(0.0) + .endArray() + .endObject() + .startObject() + .field("type", "linestring") + .startArray("coordinates") + .startArray() + .value(101.0).value(0.0) + .endArray() + .startArray() + .value(102.0).value(1.0) + .endArray() + .endArray() + .endObject() + .endArray() + .endObject().endObject(); + client().prepareIndex("test").setId("1") + .setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( + "geo", + new GeometryCollectionBuilder() + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0) + .coordinate(103.0, 3.0).coordinate(103.0, -1.0) + .coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + filter = QueryBuilders.geoShapeQuery( + "geo", + new GeometryCollectionBuilder().polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder() + .polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0) + .coordinate(103.0, -1.0).coordinate(99.0, -1.0))) + .polygon( + new PolygonBuilder(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0) + .coordinate(193.0, 13.0).coordinate(193.0, -11.0) + .coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + // no shape + filter = QueryBuilders.geoShapeQuery("geo", new GeometryCollectionBuilder()); + result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) + .setPostFilter(filter).get(); + assertSearchResponse(result); + assertHitCount(result, 0); + } } From 4d3676bc6a3e0e319d8fb44e3c9da196ef764207 Mon Sep 17 00:00:00 2001 From: djptek Date: Fri, 24 Jan 2020 16:58:12 +0100 Subject: [PATCH 18/18] rectified Checkstyle rule violations --- .../search/geo/GeoQueryTests.java | 9 +++++---- .../search/geo/GeoShapeQueryTests.java | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java index 91b27fb4e3579..6b00f4a24ebb4 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoQueryTests.java @@ -22,7 +22,7 @@ import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.geo.builders.*; +import org.elasticsearch.common.geo.builders.EnvelopeBuilder; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.test.ESSingleNodeTestCase; @@ -30,10 +30,11 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; +import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; public abstract class GeoQueryTests extends ESSingleNodeTestCase { diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 08bbcc5b2c265..347826c02cb50 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -53,8 +53,6 @@ import java.io.IOException; import java.util.Locale; -import static org.apache.lucene.util.LuceneTestCase.expectThrows; -import static org.apache.lucene.util.LuceneTestCase.random; import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; @@ -65,11 +63,9 @@ import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.nullValue; public class GeoShapeQueryTests extends GeoQueryTests { protected static final String[] PREFIX_TREES = new String[] { @@ -462,7 +458,10 @@ public void testPointQuery() throws Exception { gcb.shape(pb); // don't use random as permits quadtree - String mapping = Strings.toString(randomBoolean() ? createDefaultMapping() : createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); + String mapping = Strings.toString( + randomBoolean() ? + createDefaultMapping() : + createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); @@ -497,7 +496,10 @@ public void testContainsShapeQuery() throws Exception { } // don't use random mapping as permits quadtree - String mapping = Strings.toString(usePrefixTrees ? createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE) : createDefaultMapping()); + String mapping = Strings.toString( + usePrefixTrees ? + createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE) : + createDefaultMapping()); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen(); @@ -525,7 +527,10 @@ public void testExistsQuery() throws Exception { GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - String mapping = Strings.toString(randomBoolean() ? createDefaultMapping() : createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); + String mapping = Strings.toString( + randomBoolean() ? + createDefaultMapping() : + createPrefixTreeMapping(LegacyGeoShapeFieldMapper.DeprecatedParameters.PrefixTrees.QUADTREE)); client().admin().indices().prepareCreate("test").setMapping(mapping).get(); ensureGreen();