diff --git a/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/GeoQueryBuilder.java b/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/GeoQueryBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..6bb1234625718808ab3e95234f214ca9cf9a6896 --- /dev/null +++ b/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/GeoQueryBuilder.java @@ -0,0 +1,118 @@ +// Copyright © Schlumberger +// +// Licensed 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.opengroup.osdu.search.provider.azure.provider.impl; + +import org.elasticsearch.common.geo.GeoPoint; +import org.elasticsearch.common.geo.builders.CircleBuilder; +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.MultiPolygonBuilder; +import org.elasticsearch.common.geo.builders.PolygonBuilder; +import org.elasticsearch.common.unit.DistanceUnit; +import org.elasticsearch.index.query.QueryBuilder; +import org.locationtech.jts.geom.Coordinate; +import org.opengroup.osdu.core.common.model.http.AppException; +import org.opengroup.osdu.core.common.model.search.Point; +import org.opengroup.osdu.core.common.model.search.Polygon; +import org.opengroup.osdu.core.common.model.search.SpatialFilter; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; +import static org.elasticsearch.index.query.QueryBuilders.geoPolygonQuery; +import static org.elasticsearch.index.query.QueryBuilders.geoWithinQuery; + +public final class GeoQueryBuilder { + + private static final int MINIMUM_POLYGON_POINTS_SIZE = 4; + + public QueryBuilder getGeoQuery(SpatialFilter spatialFilter) throws IOException { + if (spatialFilter.getByBoundingBox() != null) { + return getBoundingBoxQuery(spatialFilter); + } else if (spatialFilter.getByDistance() != null) { + return getDistanceQuery(spatialFilter); + } else if (spatialFilter.getByGeoPolygon() != null) { + return getPolygonQuery(spatialFilter); + } else if (spatialFilter.getByIntersection() != null) { + return getIntersectionQuery(spatialFilter); + } + return null; + } + + private QueryBuilder getPolygonQuery(SpatialFilter spatialFilter) throws IOException { + List<Point> queryPolygon = spatialFilter.getByGeoPolygon().getPoints(); + List<Coordinate> points = new ArrayList<>(); + if (!queryPolygon.get(0).equals(queryPolygon.get(queryPolygon.size() - 1))) { + List<Point> closedRing = new ArrayList<>(); + closedRing.addAll(queryPolygon); + closedRing.add(queryPolygon.get(0)); + spatialFilter.getByGeoPolygon().setPoints(closedRing); + } + for (Point point : spatialFilter.getByGeoPolygon().getPoints()) { + points.add(new Coordinate(point.getLongitude(), point.getLatitude())); + } + CoordinatesBuilder cb = new CoordinatesBuilder().coordinates(points); + return geoWithinQuery(spatialFilter.getField(), new PolygonBuilder(cb)).ignoreUnmapped(true); + } + + private QueryBuilder getBoundingBoxQuery(SpatialFilter spatialFilter) throws IOException { + Coordinate topLeft = new Coordinate(spatialFilter.getByBoundingBox().getTopLeft().getLongitude(), spatialFilter.getByBoundingBox().getTopLeft().getLatitude()); + Coordinate bottomRight = new Coordinate(spatialFilter.getByBoundingBox().getBottomRight().getLongitude(), spatialFilter.getByBoundingBox().getBottomRight().getLatitude()); + return geoWithinQuery(spatialFilter.getField(), new EnvelopeBuilder(topLeft, bottomRight)).ignoreUnmapped(true); + } + + private QueryBuilder getDistanceQuery(SpatialFilter spatialFilter) throws IOException { + Coordinate center = new Coordinate(spatialFilter.getByDistance().getPoint().getLongitude(), spatialFilter.getByDistance().getPoint().getLatitude()); + CircleBuilder circleBuilder = new CircleBuilder().center(center).radius(spatialFilter.getByDistance().getDistance(), DistanceUnit.METERS); + return geoWithinQuery(spatialFilter.getField(), circleBuilder).ignoreUnmapped(true); + } + + private QueryBuilder getIntersectionQuery(SpatialFilter spatialFilter) throws IOException { + MultiPolygonBuilder multiPolygonBuilder = new MultiPolygonBuilder(); + for (Polygon polygon : spatialFilter.getByIntersection().getPolygons()) { + List<Coordinate> coordinates = new ArrayList<>(); + for (Point point : polygon.getPoints()) { + coordinates.add(new Coordinate(point.getLongitude(), point.getLatitude())); + } + + checkPolygon(coordinates); + + CoordinatesBuilder cb = new CoordinatesBuilder().coordinates(coordinates); + multiPolygonBuilder.polygon(new PolygonBuilder(cb)); + } + + GeometryCollectionBuilder geometryCollection = new GeometryCollectionBuilder(); + geometryCollection.shape(multiPolygonBuilder); + return geoIntersectionQuery(spatialFilter.getField(), geometryCollection.buildGeometry()).ignoreUnmapped(true); + } + + private void checkPolygon(List<Coordinate> coordinates) { + if (coordinates.size() < MINIMUM_POLYGON_POINTS_SIZE || + ( + coordinates.get(0).x != coordinates.get(coordinates.size() - 1).x + || coordinates.get(0).y != coordinates.get(coordinates.size() - 1).y + ) + ) { + throw new AppException(HttpServletResponse.SC_BAD_REQUEST, "Bad Request", + String.format( + "Polygons must have at least %s points and the first point must match the last point", + MINIMUM_POLYGON_POINTS_SIZE)); + } + } +} diff --git a/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryBase.java b/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryBase.java index d821f2abe5a7debde0b34f56cbc2d290c6a82b7d..d32a195c4369921f511ab62db1be5ff48fd4af78 100644 --- a/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryBase.java +++ b/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryBase.java @@ -15,22 +15,13 @@ package org.opengroup.osdu.search.provider.azure.provider.impl; import com.google.common.base.Strings; -import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.common.geo.GeoPoint; -import org.elasticsearch.common.geo.builders.CircleBuilder; -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.MultiPolygonBuilder; -import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.text.Text; -import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; @@ -47,14 +38,11 @@ import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.elasticsearch.search.sort.FieldSortBuilder; -import org.locationtech.jts.geom.Coordinate; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.entitlements.AclRole; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.core.common.model.search.AggregationResponse; -import org.opengroup.osdu.core.common.model.search.Point; -import org.opengroup.osdu.core.common.model.search.Polygon; import org.opengroup.osdu.core.common.model.search.Query; import org.opengroup.osdu.core.common.model.search.QueryRequest; import org.opengroup.osdu.core.common.model.search.QueryUtils; @@ -64,7 +52,6 @@ import org.opengroup.osdu.search.policy.service.IPolicyService; import org.opengroup.osdu.search.provider.azure.config.ElasticLoggingConfig; import org.opengroup.osdu.search.provider.azure.utils.DependencyLogger; import org.opengroup.osdu.search.provider.interfaces.IProviderHeaderService; -import org.opengroup.osdu.search.service.IFieldMappingTypeService; import org.opengroup.osdu.search.util.AggregationParserUtil; import org.opengroup.osdu.search.util.CrossTenantUtils; import org.opengroup.osdu.search.util.IDetailedBadRequestMessageUtil; @@ -84,13 +71,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static org.elasticsearch.index.query.QueryBuilders.geoBoundingBoxQuery; -import static org.elasticsearch.index.query.QueryBuilders.geoDistanceQuery; -import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery; -import static org.elasticsearch.index.query.QueryBuilders.geoPolygonQuery; -import static org.elasticsearch.index.query.QueryBuilders.geoWithinQuery; -import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery; -import static org.elasticsearch.index.query.QueryBuilders.termsQuery; import static org.opengroup.osdu.search.provider.azure.utils.DependencyLogger.CURSOR_QUERY_DEPENDENCY_NAME; import static org.opengroup.osdu.search.provider.azure.utils.DependencyLogger.QUERY_DEPENDENCY_NAME; @@ -104,8 +84,6 @@ abstract class QueryBase { private IProviderHeaderService providerHeaderService; @Inject private CrossTenantUtils crossTenantUtils; - @Inject - private IFieldMappingTypeService fieldMappingTypeService; @Autowired(required = false) private IPolicyService iPolicyService; @Autowired @@ -114,16 +92,17 @@ abstract class QueryBase { private ISortParserUtil sortParserUtil; @Autowired private IDetailedBadRequestMessageUtil detailedBadRequestMessageUtil; - @Autowired private ElasticLoggingConfig elasticLoggingConfig; - @Autowired @Qualifier("azureUtilsDependencyLogger") private DependencyLogger dependencyLogger; - private static final String GEO_SHAPE_INDEXED_TYPE = "geo_shape"; - private static final int MINIMUM_POLYGON_POINTS_SIZE = 4; + private final GeoQueryBuilder geoQueryBuilder; + + public QueryBase() { + this.geoQueryBuilder = new GeoQueryBuilder(); + } // if returnedField contains property matching from excludes than query result will NOT include that property private final Set<String> excludes = new HashSet<>(Arrays.asList(RecordMetaAttribute.X_ACL.getValue())); @@ -133,50 +112,25 @@ abstract class QueryBase { private final TimeValue REQUEST_TIMEOUT = TimeValue.timeValueMinutes(1); - private boolean useGeoShapeQuery = false; - QueryBuilder buildQuery(String simpleQuery, SpatialFilter spatialFilter, boolean asOwner) throws AppException, IOException { - QueryBuilder textQueryBuilder = null; - QueryBuilder spatialQueryBuilder = null; BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); if (!Strings.isNullOrEmpty(simpleQuery)) { - textQueryBuilder = queryParserUtil.buildQueryBuilderFromQueryString(simpleQuery); + QueryBuilder textQueryBuilder = queryParserUtil.buildQueryBuilderFromQueryString(simpleQuery); + if (textQueryBuilder != null) { + queryBuilder.must(textQueryBuilder); + } } // use only one of the spatial request if (spatialFilter != null) { - if (useGeoShapeQuery) { - if (spatialFilter.getByBoundingBox() != null) { - spatialQueryBuilder = getGeoShapeBoundingBoxQuery(spatialFilter); - } else if (spatialFilter.getByDistance() != null) { - spatialQueryBuilder = getGeoShapeDistanceQuery(spatialFilter); - } else if (spatialFilter.getByGeoPolygon() != null) { - spatialQueryBuilder = getGeoShapePolygonQuery(spatialFilter); - } else if (spatialFilter.getByIntersection() != null) { - spatialQueryBuilder = getGeoShapeIntersectionQuery(spatialFilter); - } - } else { - if (spatialFilter.getByBoundingBox() != null) { - spatialQueryBuilder = getBoundingBoxQuery(spatialFilter); - } else if (spatialFilter.getByDistance() != null) { - spatialQueryBuilder = getDistanceQuery(spatialFilter); - } else if (spatialFilter.getByGeoPolygon() != null) { - spatialQueryBuilder = getGeoPolygonQuery(spatialFilter); - } else if (spatialFilter.getByIntersection() != null) { - spatialQueryBuilder = getGeoShapeIntersectionQuery(spatialFilter); - } + QueryBuilder spatialQueryBuilder = this.geoQueryBuilder.getGeoQuery(spatialFilter); + if (spatialQueryBuilder != null) { + queryBuilder.filter().add(spatialQueryBuilder); } } - if (textQueryBuilder != null) { - queryBuilder.must(textQueryBuilder); - } - if (spatialQueryBuilder != null) { - queryBuilder.filter().add(spatialQueryBuilder); - } - if (this.iPolicyService != null) { String compiledESPolicy = this.iPolicyService.getCompiledPolicy(providerHeaderService); WrapperQueryBuilder wrapperQueryBuilder = new WrapperQueryBuilder(compiledESPolicy); @@ -204,92 +158,6 @@ abstract class QueryBase { return queryBuilder; } - private QueryBuilder getSimpleQuery(String searchQuery) { - - // if query is empty , then put * - String query = StringUtils.isNotBlank(searchQuery) ? searchQuery : "*"; - return queryStringQuery(query).allowLeadingWildcard(false); - } - - private QueryBuilder getBoundingBoxQuery(SpatialFilter spatialFilter) throws AppException { - - GeoPoint topLeft = new GeoPoint(spatialFilter.getByBoundingBox().getTopLeft().getLatitude(), spatialFilter.getByBoundingBox().getTopLeft().getLongitude()); - GeoPoint bottomRight = new GeoPoint(spatialFilter.getByBoundingBox().getBottomRight().getLatitude(), spatialFilter.getByBoundingBox().getBottomRight().getLongitude()); - return geoBoundingBoxQuery(spatialFilter.getField()).setCorners(topLeft, bottomRight).ignoreUnmapped(true); - } - - private QueryBuilder getDistanceQuery(SpatialFilter spatialFilter) throws AppException { - - return geoDistanceQuery(spatialFilter.getField()) - .point(spatialFilter.getByDistance().getPoint().getLatitude(), spatialFilter.getByDistance().getPoint().getLongitude()) - .distance(spatialFilter.getByDistance().getDistance(), DistanceUnit.METERS).ignoreUnmapped(true); - } - - private QueryBuilder getGeoPolygonQuery(SpatialFilter spatialFilter) throws AppException { - - List<GeoPoint> points = new ArrayList<>(); - for (Point point : spatialFilter.getByGeoPolygon().getPoints()) { - points.add(new GeoPoint(point.getLatitude(), point.getLongitude())); - } - return geoPolygonQuery(spatialFilter.getField(), points).ignoreUnmapped(true); - } - - private QueryBuilder getGeoShapePolygonQuery(SpatialFilter spatialFilter) throws IOException { - - List<Coordinate> points = new ArrayList<>(); - for (Point point : spatialFilter.getByGeoPolygon().getPoints()) { - points.add(new Coordinate(point.getLongitude(), point.getLatitude())); - } - CoordinatesBuilder cb = new CoordinatesBuilder().coordinates(points); - return geoWithinQuery(spatialFilter.getField(), new PolygonBuilder(cb)).ignoreUnmapped(true); - } - - private QueryBuilder getGeoShapeBoundingBoxQuery(SpatialFilter spatialFilter) throws IOException { - - Coordinate topLeft = new Coordinate(spatialFilter.getByBoundingBox().getTopLeft().getLongitude(), spatialFilter.getByBoundingBox().getTopLeft().getLatitude()); - Coordinate bottomRight = new Coordinate(spatialFilter.getByBoundingBox().getBottomRight().getLongitude(), spatialFilter.getByBoundingBox().getBottomRight().getLatitude()); - return geoWithinQuery(spatialFilter.getField(), new EnvelopeBuilder(topLeft, bottomRight)).ignoreUnmapped(true); - } - - private QueryBuilder getGeoShapeDistanceQuery(SpatialFilter spatialFilter) throws IOException { - Coordinate center = new Coordinate(spatialFilter.getByDistance().getPoint().getLongitude(), spatialFilter.getByDistance().getPoint().getLatitude()); - CircleBuilder circleBuilder = new CircleBuilder().center(center).radius(spatialFilter.getByDistance().getDistance(), DistanceUnit.METERS); - return geoWithinQuery(spatialFilter.getField(), circleBuilder).ignoreUnmapped(true); - } - - private QueryBuilder getGeoShapeIntersectionQuery(SpatialFilter spatialFilter) throws IOException { - MultiPolygonBuilder multiPolygonBuilder = new MultiPolygonBuilder(); - for (Polygon polygon : spatialFilter.getByIntersection().getPolygons()) { - List<Coordinate> coordinates = new ArrayList<>(); - for (Point point : polygon.getPoints()) { - coordinates.add(new Coordinate(point.getLongitude(), point.getLatitude())); - } - - checkPolygon(coordinates); - - CoordinatesBuilder cb = new CoordinatesBuilder().coordinates(coordinates); - multiPolygonBuilder.polygon(new PolygonBuilder(cb)); - } - - GeometryCollectionBuilder geometryCollection = new GeometryCollectionBuilder(); - geometryCollection.shape(multiPolygonBuilder); - return geoIntersectionQuery(spatialFilter.getField(), geometryCollection.buildGeometry()).ignoreUnmapped(true); - } - - private void checkPolygon(List<Coordinate> coordinates) { - if (coordinates.size() < MINIMUM_POLYGON_POINTS_SIZE || - ( - coordinates.get(0).x != coordinates.get(coordinates.size() - 1).x - || coordinates.get(0).y != coordinates.get(coordinates.size() - 1).y - ) - ) { - throw new AppException(HttpServletResponse.SC_BAD_REQUEST, "Bad Request", - String.format( - "Polygons must have at least %s points and the first point must match the last point", - MINIMUM_POLYGON_POINTS_SIZE)); - } - } - String getIndex(Query request) { return this.crossTenantUtils.getIndexName(request); } @@ -394,9 +262,6 @@ abstract class QueryBase { try { String index = this.getIndex(searchRequest); - if (searchRequest.getSpatialFilter() != null) { - useGeoShapeQuery = this.useGeoShapeQuery(client, searchRequest, index); - } elasticSearchRequest = createElasticRequest(searchRequest, index); if (searchRequest.getSort() != null) { List<FieldSortBuilder> sortBuilders = this.sortParserUtil.getSortQuery(client, searchRequest.getSort(), index); @@ -460,13 +325,6 @@ abstract class QueryBase { return searchResponse.status().getStatus(); } - private boolean useGeoShapeQuery(RestHighLevelClient client, Query searchRequest, String index) throws IOException { - Set<String> indexedTypes = this.fieldMappingTypeService.getFieldTypes(client, searchRequest.getSpatialFilter().getField(), index); - // fallback to geo_point search if mixed type found for spatialFilter.field - if (indexedTypes.isEmpty() || indexedTypes.size() > 1) return false; - return indexedTypes.contains(GEO_SHAPE_INDEXED_TYPE); - } - abstract SearchRequest createElasticRequest(Query request, String index) throws AppException, IOException; abstract void querySuccessAuditLogger(Query request); diff --git a/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryServiceImpl.java b/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryServiceImpl.java index 136d916006cce36abe48c34fcf8ad07ab3bb0a2f..3783b9f0e38c32ede75035cb92f631764540926c 100644 --- a/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryServiceImpl.java +++ b/provider/search-azure/src/main/java/org/opengroup/osdu/search/provider/azure/provider/impl/QueryServiceImpl.java @@ -43,8 +43,6 @@ public class QueryServiceImpl extends QueryBase implements IQueryService { @Inject private AuditLogger auditLogger; @Inject - private SearchConfigurationProperties configurationProperties; - @Inject private IAggregationParserUtil aggregationParserUtil; @Override diff --git a/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/GeoQueryBuilderTest.java b/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/GeoQueryBuilderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..692679b58f9184738dee801095f595ff341c6b60 --- /dev/null +++ b/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/GeoQueryBuilderTest.java @@ -0,0 +1,162 @@ +// Copyright © Schlumberger +// +// Licensed 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.opengroup.osdu.search.provider.azure.provider.impl; + +import org.elasticsearch.geometry.Circle; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.index.query.GeoShapeQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.opengroup.osdu.core.common.model.search.Point; +import org.opengroup.osdu.core.common.model.search.Polygon; +import org.opengroup.osdu.core.common.model.search.SpatialFilter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(MockitoJUnitRunner.class) +public class GeoQueryBuilderTest { + + private static final String GEO_FIELD = "data.SpatialLocation.Wgs84Coordinates"; + @InjectMocks + private GeoQueryBuilder sut; + + @Test + public void should_provide_valid_distanceQuery() throws IOException { + SpatialFilter spatialFilter = new SpatialFilter(); + spatialFilter.setField(GEO_FIELD); + SpatialFilter.ByDistance circl = new SpatialFilter.ByDistance(); + Point center = new Point(1.02, -8.61); + circl.setDistance(1000); + circl.setPoint(center); + spatialFilter.setByDistance(circl); + + QueryBuilder queryBuilder = this.sut.getGeoQuery(spatialFilter); + + assertNotNull(queryBuilder); + GeoShapeQueryBuilder shapeQueryBuilder = (GeoShapeQueryBuilder) queryBuilder; + assertEquals(GEO_FIELD, shapeQueryBuilder.fieldName()); + assertEquals(true, shapeQueryBuilder.ignoreUnmapped()); + assertTrue(shapeQueryBuilder.shape() instanceof Circle); + assertEquals("WITHIN", shapeQueryBuilder.relation().name()); + Circle circle = (Circle) shapeQueryBuilder.shape(); + assertEquals(-8.61, circle.getX(), 0.000001); + assertEquals(1.02, circle.getY(), 0.000001); + } + + @Test + public void should_provide_valid_boundingBoxQuery() throws IOException { + SpatialFilter spatialFilter = new SpatialFilter(); + spatialFilter.setField(GEO_FIELD); + SpatialFilter.ByBoundingBox boundingBox = new SpatialFilter.ByBoundingBox(); + Point topLeft = new Point(90, -180); + Point bottomRight = new Point(-90, 180); + boundingBox.setTopLeft(topLeft); + boundingBox.setBottomRight(bottomRight); + spatialFilter.setByBoundingBox(boundingBox); + + QueryBuilder queryBuilder = this.sut.getGeoQuery(spatialFilter); + + assertNotNull(queryBuilder); + GeoShapeQueryBuilder shapeQueryBuilder = (GeoShapeQueryBuilder) queryBuilder; + assertEquals(GEO_FIELD, shapeQueryBuilder.fieldName()); + assertEquals(true, shapeQueryBuilder.ignoreUnmapped()); + assertTrue(shapeQueryBuilder.shape() instanceof Rectangle); + assertEquals("WITHIN", shapeQueryBuilder.relation().name()); + Rectangle rectangle = (Rectangle) shapeQueryBuilder.shape(); + assertEquals(90, rectangle.getMaxLat(), 0.01); + assertEquals(180, rectangle.getMaxLon(), 0.01); + assertEquals(-90, rectangle.getMinLat(), 0.01); + assertEquals(-180, rectangle.getMinLon(), 0.01); + } + + @Test + public void should_provide_valid_polygonQuery() throws IOException { + SpatialFilter spatialFilter = new SpatialFilter(); + spatialFilter.setField(GEO_FIELD); + SpatialFilter.ByGeoPolygon geoPolygon = new SpatialFilter.ByGeoPolygon(); + Point point = new Point(1.02, -8.61); + Point point1 = new Point(1.02, -2.48); + Point point2 = new Point(10.74, -2.48); + Point point3 = new Point(10.74, -8.61); + Point point4 = new Point(1.02, -8.61); + List<Point> points = new ArrayList<>(); + points.add(point); + points.add(point1); + points.add(point2); + points.add(point3); + points.add(point4); + geoPolygon.setPoints(points); + spatialFilter.setByGeoPolygon(geoPolygon); + + QueryBuilder queryBuilder = this.sut.getGeoQuery(spatialFilter); + + assertNotNull(queryBuilder); + GeoShapeQueryBuilder shapeQueryBuilder = (GeoShapeQueryBuilder) queryBuilder; + assertEquals(GEO_FIELD, shapeQueryBuilder.fieldName()); + assertEquals(true, shapeQueryBuilder.ignoreUnmapped()); + assertTrue(shapeQueryBuilder.shape() instanceof org.elasticsearch.geometry.Polygon); + assertEquals("WITHIN", shapeQueryBuilder.relation().name()); + org.elasticsearch.geometry.Polygon expectedPolygon = (org.elasticsearch.geometry.Polygon) shapeQueryBuilder.shape(); + assertArrayEquals(new double[]{1.02, 1.02, 10.74, 10.74, 1.02}, expectedPolygon.getPolygon().getLats(), 0.01); + assertArrayEquals(new double[]{-8.61, -2.48, -2.48, -8.61, -8.61}, expectedPolygon.getPolygon().getLons(), 0.01); + } + + @Test + public void should_provide_valid_intersectionQuery() throws IOException { + SpatialFilter spatialFilter = new SpatialFilter(); + spatialFilter.setField(GEO_FIELD); + SpatialFilter.ByIntersection byIntersection = new SpatialFilter.ByIntersection(); + Polygon polygon = new Polygon(); + Point point = new Point(1.02, -8.61); + Point point1 = new Point(1.02, -2.48); + Point point2 = new Point(10.74, -2.48); + Point point3 = new Point(10.74, -8.61); + Point point4 = new Point(1.02, -8.61); + List<Point> points = new ArrayList<>(); + points.add(point); + points.add(point1); + points.add(point2); + points.add(point3); + points.add(point4); + polygon.setPoints(points); + List<Polygon> polygons = new ArrayList<>(); + polygons.add(polygon); + byIntersection.setPolygons(polygons); + spatialFilter.setByIntersection(byIntersection); + + QueryBuilder queryBuilder = this.sut.getGeoQuery(spatialFilter); + + assertNotNull(queryBuilder); + GeoShapeQueryBuilder shapeQueryBuilder = (GeoShapeQueryBuilder) queryBuilder; + assertEquals(GEO_FIELD, shapeQueryBuilder.fieldName()); + assertEquals(true, shapeQueryBuilder.ignoreUnmapped()); + assertEquals("INTERSECTS", shapeQueryBuilder.relation().name()); + assertTrue(shapeQueryBuilder.shape() instanceof org.elasticsearch.geometry.GeometryCollection); + org.elasticsearch.geometry.GeometryCollection geometryCollection = (org.elasticsearch.geometry.GeometryCollection) shapeQueryBuilder.shape(); + org.elasticsearch.geometry.MultiPolygon multiPolygon = (org.elasticsearch.geometry.MultiPolygon) geometryCollection.get(0); + assertArrayEquals(new double[]{1.02, 1.02, 10.74, 10.74, 1.02}, multiPolygon.get(0).getPolygon().getLats(), 0.01); + assertArrayEquals(new double[]{-8.61, -2.48, -2.48, -8.61, -8.61}, multiPolygon.get(0).getPolygon().getLons(), 0.01); + } +} diff --git a/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/QueryServiceImplTest.java b/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/QueryServiceImplTest.java index f32e7152a154487a7eebba90148a7acf540eda27..88d637e1135d1bdf6ee994a877faa58da4f28401 100644 --- a/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/QueryServiceImplTest.java +++ b/provider/search-azure/src/test/java/org/opengroup/osdu/search/provider/azure/provider.impl/QueryServiceImplTest.java @@ -164,9 +164,6 @@ public class QueryServiceImplTest { @Mock private IProviderHeaderService providerHeaderService; - @Mock - private FieldMappingTypeService fieldMappingTypeService; - @Spy private SearchConfigurationProperties properties = new SearchConfigurationProperties(); @@ -188,6 +185,9 @@ public class QueryServiceImplTest { @Mock private DependencyLogger dependencyLogger; + @Mock + private GeoQueryBuilder geoQueryBuilder; + @InjectMocks private QueryServiceImpl sut; @@ -199,7 +199,6 @@ public class QueryServiceImplTest { doReturn(indexName).when(crossTenantUtils).getIndexName(any()); doReturn(client).when(elasticClientHandler).createRestClient(); doReturn(spatialFilter).when(searchRequest).getSpatialFilter(); - doReturn(fieldName).when(spatialFilter).getField(); when(elasticLoggingConfig.getEnabled()).thenReturn(false); when(elasticLoggingConfig.getThreshold()).thenReturn(200L); // doReturn(searchResponse).when(client).search(any(), any(RequestOptions.class)); @@ -219,9 +218,7 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_whenSearchHitsIsEmpty() throws IOException { SearchHit[] hits = {}; - Set<String> indexedTypes = new HashSet<>(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(hits).when(searchHits).getHits(); QueryResponse queryResponse = sut.queryIndex(searchRequest); @@ -235,11 +232,9 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_whenSearchHitsIsNotEmpty() throws IOException { SearchHit[] hits = {searchHit}; - Set<String> indexedTypes = new HashSet<>(); Map<String, HighlightField> highlightFields = getHighlightFields(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(hits).when(searchHits).getHits(); doReturn(highlightFields).when(searchHit).getHighlightFields(); @@ -257,10 +252,8 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_useGeoShapeQueryIsFalse_getByBoundingBox() throws IOException { SearchHit[] hits = {}; - Set<String> indexedTypes = new HashSet<>(); SpatialFilter.ByBoundingBox boundingBox = getValidBoundingBox(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(boundingBox).when(spatialFilter).getByBoundingBox(); doReturn(hits).when(searchHits).getHits(); @@ -286,12 +279,9 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_useGeoShapeQueryIsTrue_getByBoundingBox() throws IOException { SearchHit[] hits = {}; - Set<String> indexedTypes = new HashSet<>(); - indexedTypes.add(GEO_SHAPE); SpatialFilter.ByBoundingBox boundingBox = getValidBoundingBox(); doReturn(boundingBox).when(spatialFilter).getByBoundingBox(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(hits).when(searchHits).getHits(); QueryResponse queryResponse = sut.queryIndex(searchRequest); @@ -318,11 +308,9 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_useGeoShapeQueryIsFalse_getByDistance() throws IOException { SearchHit[] hits = {}; - Set<String> indexedTypes = new HashSet<>(); SpatialFilter.ByDistance distance = getDistance(1.0, dummyPoint); doReturn(distance).when(spatialFilter).getByDistance(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(hits).when(searchHits).getHits(); QueryResponse queryResponse = sut.queryIndex(searchRequest); @@ -347,12 +335,10 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_useGeoShapeQueryIsFalse_getByGeoPolygon() throws IOException { SearchHit[] hits = new SearchHit[0]; - Set<String> indexedTypes = new HashSet<>(); SpatialFilter.ByGeoPolygon geoPolygon = new SpatialFilter.ByGeoPolygon(polygonPoints); doReturn(geoPolygon).when(spatialFilter).getByGeoPolygon(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(hits).when(searchHits).getHits(); QueryResponse queryResponse = sut.queryIndex(searchRequest); @@ -373,12 +359,9 @@ public class QueryServiceImplTest { @Ignore public void testQueryBase_useGeoShapeQueryIsTrue_getByGeoPolygon() throws IOException { SearchHit[] hits = {}; - Set<String> indexedTypes = new HashSet<>(); - indexedTypes.add(GEO_SHAPE); SpatialFilter.ByGeoPolygon geoPolygon = getGeoPolygon(closedPolygonPoints); doReturn(geoPolygon).when(spatialFilter).getByGeoPolygon(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); doReturn(hits).when(searchHits).getHits(); QueryResponse queryResponse = sut.queryIndex(searchRequest); @@ -405,11 +388,8 @@ public class QueryServiceImplTest { public void testQueryBase_whenClientSearchResultsInElasticsearchStatusException_statusNotFound_throwsException() throws IOException { ElasticsearchStatusException exception = mock(ElasticsearchStatusException.class); - Set<String> indexedTypes = new HashSet<>(); - doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(RestStatus.NOT_FOUND).when(exception).status(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -425,11 +405,8 @@ public class QueryServiceImplTest { public void testQueryBase_whenClientSearchResultsInElasticsearchStatusException_statusBadRequest_throwsException() throws IOException { ElasticsearchStatusException exception = mock(ElasticsearchStatusException.class); - Set<String> indexedTypes = new HashSet<>(); - doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(RestStatus.BAD_REQUEST).when(exception).status(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -447,7 +424,6 @@ public class QueryServiceImplTest { ElasticsearchStatusException exception = new ElasticsearchStatusException("blah", RestStatus.BAD_REQUEST, new ElasticsearchException(dummySortError)); doThrow(exception).when(client).search(any(), any(RequestOptions.class)); - doReturn(new HashSet<>()).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); SortQuery sortQuery = new SortQuery(); sortQuery.setField(Collections.singletonList("data.name")); sortQuery.setOrder(Collections.singletonList(SortOrder.DESC)); @@ -469,11 +445,8 @@ public class QueryServiceImplTest { public void testQueryBase_whenClientSearchResultsInElasticsearchStatusException_statusServiceUnavailable_throwsException() throws IOException { ElasticsearchStatusException exception = mock(ElasticsearchStatusException.class); - Set<String> indexedTypes = new HashSet<>(); - doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(RestStatus.SERVICE_UNAVAILABLE).when(exception).status(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -489,11 +462,8 @@ public class QueryServiceImplTest { public void testQueryBase_whenClientSearchResultsInElasticsearchStatusException_statusTooManyRequests_throwsException() throws IOException { ElasticsearchStatusException exception = mock(ElasticsearchStatusException.class); - Set<String> indexedTypes = new HashSet<>(); - doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(RestStatus.TOO_MANY_REQUESTS).when(exception).status(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -509,12 +479,10 @@ public class QueryServiceImplTest { public void testQueryBase_IOException_ListenerTimeout_throwsException() throws IOException { IOException exception = mock(IOException.class); - Set<String> indexedTypes = new HashSet<>(); String dummyTimeoutMessage = "listener timeout after waiting for 1m"; doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(dummyTimeoutMessage).when(exception).getMessage(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -530,12 +498,10 @@ public class QueryServiceImplTest { public void testQueryBase_SocketTimeoutException_ListenerTimeout_throwsException() throws IOException { SocketTimeoutException exception = mock(SocketTimeoutException.class); - Set<String> indexedTypes = new HashSet<>(); String dummyTimeoutMessage = "60,000 milliseconds timeout on connection"; doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(dummyTimeoutMessage).when(exception).getMessage(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -551,12 +517,10 @@ public class QueryServiceImplTest { public void testQueryBase_IOException_EmptyMessage_throwsException() throws IOException { IOException exception = mock(IOException.class); - Set<String> indexedTypes = new HashSet<>(); String dummyTimeoutMessage = ""; doThrow(exception).when(client).search(any(), any(RequestOptions.class)); doReturn(dummyTimeoutMessage).when(exception).getMessage(); - doReturn(indexedTypes).when(fieldMappingTypeService).getFieldTypes(eq(client), eq(fieldName), eq(indexName)); try { sut.queryIndex(searchRequest); @@ -676,11 +640,6 @@ public class QueryServiceImplTest { Mockito.when(crossTenantUtils.getIndexName(Mockito.any())) .thenReturn(index); - Set<String> indexedTypes = new HashSet<>(); - indexedTypes.add("geo_shape"); - Mockito.when(fieldMappingTypeService.getFieldTypes(Mockito.eq(client), Mockito.anyString(), Mockito.eq(index))) - .thenReturn(indexedTypes); - Mockito.when(providerHeaderService.getDataGroupsHeader()) .thenReturn("groups");