/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/types/predicate/impl/ElasticsearchGeoPointSpatialWithinCirclePredicate.java

https://github.com/Unimarket/hibernate-search · Java · 95 lines · 71 code · 16 blank · 8 comment · 1 complexity · c98773156d6d39a99ec0b2a2ee0af3dc MD5 · raw file

  1. /*
  2. * Hibernate Search, full-text search for your domain model
  3. *
  4. * License: GNU Lesser General Public License (LGPL), version 2.1 or later
  5. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  6. */
  7. package org.hibernate.search.backend.elasticsearch.types.predicate.impl;
  8. import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor;
  9. import org.hibernate.search.backend.elasticsearch.gson.impl.JsonObjectAccessor;
  10. import org.hibernate.search.backend.elasticsearch.search.common.impl.AbstractElasticsearchCodecAwareSearchQueryElementFactory;
  11. import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexScope;
  12. import org.hibernate.search.backend.elasticsearch.search.common.impl.ElasticsearchSearchIndexValueFieldContext;
  13. import org.hibernate.search.backend.elasticsearch.search.predicate.impl.AbstractElasticsearchSingleFieldPredicate;
  14. import org.hibernate.search.backend.elasticsearch.search.predicate.impl.PredicateRequestContext;
  15. import org.hibernate.search.backend.elasticsearch.types.codec.impl.ElasticsearchFieldCodec;
  16. import org.hibernate.search.engine.search.predicate.SearchPredicate;
  17. import org.hibernate.search.engine.search.predicate.spi.SpatialWithinCirclePredicateBuilder;
  18. import org.hibernate.search.engine.spatial.DistanceUnit;
  19. import org.hibernate.search.engine.spatial.GeoPoint;
  20. import com.google.gson.JsonElement;
  21. import com.google.gson.JsonObject;
  22. public class ElasticsearchGeoPointSpatialWithinCirclePredicate extends AbstractElasticsearchSingleFieldPredicate {
  23. private static final JsonObjectAccessor GEO_DISTANCE_ACCESSOR =
  24. JsonAccessor.root().property( "geo_distance" ).asObject();
  25. private static final JsonAccessor<Double> DISTANCE_ACCESSOR =
  26. JsonAccessor.root().property( "distance" ).asDouble();
  27. private static final JsonAccessor<Boolean> IGNORE_UNMAPPED_ACCESSOR =
  28. JsonAccessor.root().property( "ignore_unmapped" ).asBoolean();
  29. private final double distanceInMeters;
  30. private final JsonElement center;
  31. private ElasticsearchGeoPointSpatialWithinCirclePredicate(Builder builder) {
  32. super( builder );
  33. distanceInMeters = builder.distanceInMeters;
  34. center = builder.center;
  35. }
  36. @Override
  37. protected JsonObject doToJsonQuery(PredicateRequestContext context, JsonObject outerObject,
  38. JsonObject innerObject) {
  39. DISTANCE_ACCESSOR.set( innerObject, distanceInMeters );
  40. innerObject.add( absoluteFieldPath, center );
  41. if ( indexNames().size() > 1 ) {
  42. // There are multiple target indexes; some of them may not declare the field.
  43. // Instruct ES to behave as if the field had no value in that case.
  44. IGNORE_UNMAPPED_ACCESSOR.set( innerObject, true );
  45. }
  46. GEO_DISTANCE_ACCESSOR.set( outerObject, innerObject );
  47. return outerObject;
  48. }
  49. public static class Factory
  50. extends
  51. AbstractElasticsearchCodecAwareSearchQueryElementFactory<SpatialWithinCirclePredicateBuilder, GeoPoint> {
  52. public Factory(ElasticsearchFieldCodec<GeoPoint> codec) {
  53. super( codec );
  54. }
  55. @Override
  56. public Builder create(ElasticsearchSearchIndexScope<?> scope, ElasticsearchSearchIndexValueFieldContext<GeoPoint> field) {
  57. return new Builder( codec, scope, field );
  58. }
  59. }
  60. private static class Builder extends AbstractBuilder implements SpatialWithinCirclePredicateBuilder {
  61. private final ElasticsearchFieldCodec<GeoPoint> codec;
  62. private double distanceInMeters;
  63. private JsonElement center;
  64. private Builder(ElasticsearchFieldCodec<GeoPoint> codec, ElasticsearchSearchIndexScope<?> scope,
  65. ElasticsearchSearchIndexValueFieldContext<GeoPoint> field) {
  66. super( scope, field );
  67. this.codec = codec;
  68. }
  69. @Override
  70. public void circle(GeoPoint center, double radius, DistanceUnit unit) {
  71. this.distanceInMeters = unit.toMeters( radius );
  72. this.center = codec.encode( center );
  73. }
  74. @Override
  75. public SearchPredicate build() {
  76. return new ElasticsearchGeoPointSpatialWithinCirclePredicate( this );
  77. }
  78. }
  79. }