/** * Require at least one of the targeted fields to point to a location within the given circle, * i.e. a location that is at most at the given distance from the given center. * * @param center The center of the bounding circle. * @param radiusInMeters The radius of the bounding circle, in meters. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext circle(GeoPoint center, double radiusInMeters) { return circle( center, radiusInMeters, DistanceUnit.METERS ); }
/** * Require at least one of the targeted fields to point to a location within the given box (~rectangle). * * @param topLeftLatitude The latitude of the top-left corner of the box. * @param topLeftLongitude The longitude of the top-left corner of the box. * @param bottomRightLatitude The latitude of the bottom-right corner of the box. * @param bottomRightLongitude The longitude of the bottom-right corner of the box. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext boundingBox(double topLeftLatitude, double topLeftLongitude, double bottomRightLatitude, double bottomRightLongitude) { return boundingBox( GeoBoundingBox.of( topLeftLatitude, topLeftLongitude, bottomRightLatitude, bottomRightLongitude ) ); } }
/** * Target the given field in the "within" predicate, * as an alternative to the already-targeted fields. * <p> * See {@link SpatialWithinPredicateContext#onField(String)} for more information on targeted fields. * * @param absoluteFieldPath The absolute path (from the document root) of the targeted field. * @return {@code this}, for method chaining. * * @see SpatialWithinPredicateContext#onField(String) */ default SpatialWithinPredicateFieldSetContext orField(String absoluteFieldPath) { return orFields( absoluteFieldPath ); }
.predicate( f -> f.spatial().within().onField( "geoPoint" ).orField( "geoPoint_1" ).boundingBox( BOUNDING_BOX_1 ).toPredicate() ) .build(); .predicate( f -> f.spatial().within().onField( "geoPoint" ).orField( "geoPoint_1" ).boundingBox( BOUNDING_BOX_2_1 ).toPredicate() ) .build(); .predicate( f -> f.spatial().within().onField( "geoPoint" ).orFields( "geoPoint_1" ).orFields( "geoPoint_2" ) .boundingBox( BOUNDING_BOX_2 ) .toPredicate() .predicate( f -> f.spatial().within().onField( "geoPoint" ).orFields( "geoPoint_1" ).orFields( "geoPoint_2" ) .boundingBox( BOUNDING_BOX_1_1 ) .toPredicate() .predicate( f -> f.spatial().within().onField( "geoPoint" ).orFields( "geoPoint_1" ).orFields( "geoPoint_2" ) .boundingBox( BOUNDING_BOX_2_2 ) .toPredicate() .predicate( f -> f.spatial().within().onFields( "geoPoint", "geoPoint_2" ).boundingBox( BOUNDING_BOX_2 ).toPredicate() ) .build(); .predicate( f -> f.spatial().within().onFields( "geoPoint", "geoPoint_2" ).boundingBox( BOUNDING_BOX_1_2 ).toPredicate() ) .build();
.predicate( f -> f.spatial().within().onField( "geoPoint" ).orField( "geoPoint_1" ).polygon( POLYGON_1 ).toPredicate() ) .build(); .predicate( f -> f.spatial().within().onField( "geoPoint" ).orField( "geoPoint_1" ).polygon( POLYGON_2_1 ).toPredicate() ) .build(); .predicate( f -> f.spatial().within().onField( "geoPoint" ).orFields( "geoPoint_1" ).orFields( "geoPoint_2" ) .polygon( POLYGON_2 ) .toPredicate() .predicate( f -> f.spatial().within().onField( "geoPoint" ).orFields( "geoPoint_1" ).orFields( "geoPoint_2" ) .polygon( POLYGON_1_1 ) .toPredicate() .predicate( f -> f.spatial().within().onField( "geoPoint" ).orFields( "geoPoint_1" ).orFields( "geoPoint_2" ) .polygon( POLYGON_2_2 ) .toPredicate() .predicate( f -> f.spatial().within().onFields( "geoPoint", "geoPoint_2" ).polygon( POLYGON_2 ).toPredicate() ) .build(); .predicate( f -> f.spatial().within().onFields( "geoPoint", "geoPoint_2" ).polygon( POLYGON_1_2 ).toPredicate() ) .build();
@Test public void boost() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool() .should( f.spatial().within().onField( "geoPoint" ).boundingBox( CHEZ_MARGOTTE_BOUNDING_BOX ) ) .should( f.match().onField( "string" ).boostedTo( 42 ).matching( OURSON_QUI_BOIT_STRING ) ) .toPredicate() ) .sort( c -> c.byScore() ) .build(); assertThat( query ) .hasDocRefHitsExactOrder( INDEX_NAME, OURSON_QUI_BOIT_ID, CHEZ_MARGOTTE_ID ); query = searchTarget.query() .asReference() .predicate( f -> f.bool() .should( f.spatial().within().onField( "geoPoint" ).boostedTo( 42 ).boundingBox( CHEZ_MARGOTTE_BOUNDING_BOX ) ) .should( f.match().onField( "string" ).matching( OURSON_QUI_BOIT_STRING ) ) .toPredicate() ) .sort( c -> c.byScore() ) .build(); assertThat( query ) .hasDocRefHitsExactOrder( INDEX_NAME, CHEZ_MARGOTTE_ID, OURSON_QUI_BOIT_ID ); }
@Test public void boost() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.bool() .should( f.spatial().within().onField( "geoPoint" ).polygon( CHEZ_MARGOTTE_POLYGON ) ) .should( f.match().onField( "string" ).boostedTo( 42 ).matching( OURSON_QUI_BOIT_STRING ) ) .toPredicate() ) .sort( c -> c.byScore() ) .build(); assertThat( query ) .hasDocRefHitsExactOrder( INDEX_NAME, OURSON_QUI_BOIT_ID, CHEZ_MARGOTTE_ID ); query = searchTarget.query() .asReference() .predicate( f -> f.bool() .should( f.spatial().within().onField( "geoPoint" ).boostedTo( 42 ).polygon( CHEZ_MARGOTTE_POLYGON ) ) .should( f.match().onField( "string" ).matching( OURSON_QUI_BOIT_STRING ) ) .toPredicate() ) .sort( c -> c.byScore() ) .build(); assertThat( query ) .hasDocRefHitsExactOrder( INDEX_NAME, CHEZ_MARGOTTE_ID, OURSON_QUI_BOIT_ID ); }
@Test public void polygon_error_null() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SubTest.expectException( "spatial().within().boundingBox() predicate with null polygon", () -> searchTarget.predicate().spatial().within().onField( "geoPoint" ).polygon( null ) ) .assertThrown() .isInstanceOf( IllegalArgumentException.class ) .hasMessageContaining( "HSEARCH900000" ); }
@Test public void unknown_field() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SubTest.expectException( "spatial().within().polygon() predicate on unknown field", () -> searchTarget.predicate().spatial().within().onField( "unknown_field" ) .polygon( POLYGON_1 ).toPredicate() ) .assertThrown() .isInstanceOf( SearchException.class ) .hasMessageContaining( "Unknown field" ) .hasMessageContaining( "'unknown_field'" ); }
/** * Require at least one of the targeted fields to point to a location within the given circle, * i.e. a location that is at most at the given distance from the given center. * * @param center The center of the bounding circle. * @param radiusInMeters The radius of the bounding circle, in meters. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext circle(GeoPoint center, double radiusInMeters) { return circle( center, radiusInMeters, DistanceUnit.METERS ); }
/** * Require at least one of the targeted fields to point to a location within the given box (~rectangle). * * @param topLeftLatitude The latitude of the top-left corner of the box. * @param topLeftLongitude The longitude of the top-left corner of the box. * @param bottomRightLatitude The latitude of the bottom-right corner of the box. * @param bottomRightLongitude The longitude of the bottom-right corner of the box. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext boundingBox(double topLeftLatitude, double topLeftLongitude, double bottomRightLatitude, double bottomRightLongitude) { return boundingBox( GeoBoundingBox.of( topLeftLatitude, topLeftLongitude, bottomRightLatitude, bottomRightLongitude ) ); } }
/** * Target the given field in the "within" predicate, * as an alternative to the already-targeted fields. * <p> * See {@link SpatialWithinPredicateContext#onField(String)} for more information on targeted fields. * * @param absoluteFieldPath The absolute path (from the document root) of the targeted field. * @return {@code this}, for method chaining. * * @see SpatialWithinPredicateContext#onField(String) */ default SpatialWithinPredicateFieldSetContext orField(String absoluteFieldPath) { return orFields( absoluteFieldPath ); }
@Test public void unsupported_field_types() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SubTest.expectException( "spatial().within().polygon() predicate on field with unsupported type", () -> searchTarget.predicate().spatial().within().onField( "string" ).polygon( POLYGON_1 ) ) .assertThrown() .isInstanceOf( SearchException.class ) .hasMessageContaining( "Spatial predicates are not supported by" ) .satisfies( FailureReportUtils.hasContext( EventContexts.fromIndexFieldAbsolutePath( "string" ) ) ); }
/** * Require at least one of the targeted fields to point to a location within the given circle, * i.e. a location that is at most at the given distance from the given center. * * @param latitude The latitude of the center of the bounding circle. * @param longitude The longitude of the center of the bounding circle. * @param radiusInMeters The radius of the bounding circle, in meters. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext circle(double latitude, double longitude, double radiusInMeters) { return circle( GeoPoint.of( latitude, longitude ), radiusInMeters, DistanceUnit.METERS ); }
@Test public void boundingBox_error_null() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SubTest.expectException( "spatial().within().boundingBox() predicate with null bounding box", () -> searchTarget.predicate().spatial().within().onField( "geoPoint" ).boundingBox( null ) ) .assertThrown() .isInstanceOf( IllegalArgumentException.class ) .hasMessageContaining( "HSEARCH900000" ); }
@Test public void within_polygon() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SearchQuery<DocumentReference> query = searchTarget.query() .asReference() .predicate( f -> f.spatial().within().onField( "geoPoint" ).polygon( POLYGON_2 ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, IMOUTO_ID, CHEZ_MARGOTTE_ID ); query = searchTarget.query() .asReference() .predicate( f -> f.spatial().within().onField( "geoPoint" ).polygon( POLYGON_1 ).toPredicate() ) .build(); assertThat( query ) .hasDocRefHitsAnyOrder( INDEX_NAME, OURSON_QUI_BOIT_ID, IMOUTO_ID ); }
/** * Require at least one of the targeted fields to point to a location within the given circle, * i.e. a location that is at most at the given distance from the given center. * * @param latitude The latitude of the center of the bounding circle. * @param longitude The longitude of the center of the bounding circle. * @param radiusInMeters The radius of the bounding circle, in meters. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext circle(double latitude, double longitude, double radiusInMeters) { return circle( GeoPoint.of( latitude, longitude ), radiusInMeters, DistanceUnit.METERS ); }
@Test public void unknown_field() { StubMappingSearchTarget searchTarget = indexManager.createSearchTarget(); SubTest.expectException( "spatial().within().boundingBox() predicate on unknown field", () -> searchTarget.predicate().spatial().within().onField( "unknown_field" ) .boundingBox( BOUNDING_BOX_1 ).toPredicate() ) .assertThrown() .isInstanceOf( SearchException.class ) .hasMessageContaining( "Unknown field" ) .hasMessageContaining( "'unknown_field'" ); }
/** * Require at least one of the targeted fields to point to a location within the given circle, * i.e. a location that is at most at the given distance from the given center. * * @param latitude The latitude of the center of the bounding circle. * @param longitude The longitude of the center of the bounding circle. * @param radius The radius of the bounding circle, in the unit defined by parameter {@code unit}. * @param unit The unit used for the radius. * @return A context allowing to get the resulting predicate. */ default SearchPredicateTerminalContext circle(double latitude, double longitude, double radius, DistanceUnit unit) { return circle( GeoPoint.of( latitude, longitude ), radius, unit ); }