Reputation: 546
I have an Entity A with Hibernate Search @Spatial data like this:
@Entity
@Spatial(spatialMode = SpatialMode.HASH)
@Indexed
public class A {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
private Double latitude;
private Double longitude;
@Spatial(spatialMode = SpatialMode.HASH)
@SortableField
public Coordinates getLocation() {
return new Coordinates() {
@Override
public Double getLatitude() {
return latitude;
}
@Override
public Double getLongitude() {
return longitude;
}
};
}
@ManyToMany(fetch = FetchType.EAGER)
@IndexedEmbedded
private Set<B> multipleB = new HashSet<>();
}
Entity A has a ManyToMany Relationship with Entity B. Entity A has Spatial Information that are important to Entity B. Now I want to perform a Spatial Query on Entity B, that uses the location Information of Entity A.
@Entity
@Indexed
public class B {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
@ManyToMany
@ContainedIn
private Set<A> multipleA = new HashSet<>();
}
I tried to do a Query for Entity B like this:
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(B.class).get();
Query luceneQuery = qb.
spatial()
.onField("multipleA.location")
.within(kmRadius, Unit.KM)
.ofLatitude(centerLatitude)
.andLongitude(centerLongitude)
.createQuery();
However the Problem is, that when I query like this I get the following exception:
The field 'B#multipleA.location' used for the spatial query is not configured as spatial field. Check the proper use of @Spatial respectively SpatialFieldBridge.
Is there a way to do spatial queries on Entities of Type B that use the spatial data from the connected Entities A with @ManyToMany?
For my Queries it would also be acceptable if the same Entity B is returned multiple times for each connected Entity A (like it would with a join).
Example (a_1 is the closest Entity A)
Database: b_1 -> (a_1, a_2), b_2 -> (a_1), b_3 -> (a_2, a_3)
Query Result:
b_1 (a_1 is the closest)
b_2 (a_1)
b_1 (a_2 is the second closest)
b_3 (a_2)
b_3 (a_3)
Upvotes: 0
Views: 416
Reputation: 9977
Multi-valued locations are not supported in Hibernate Search; even if you manage to index it, the query just won't work properly (it will mix the latitude and longitude from different points).
The only way I can see this working would be if you modeled your many-to-many association as an entity, indexed that entity, and queried it instead of B
.
Also, note the error you're getting is related to another issue: the field you're targeting does not exist. If you wanted it to exist, you would need to add an @IndexedEmbedded
on B#multipleA
.
Here is something that should work better:
@Entity
@Spatial(spatialMode = SpatialMode.HASH)
@Indexed
public class A {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
private Double latitude;
private Double longitude;
@Latitude
public Double getLatitude() {
return latitude;
}
@Longitude
public Double getLongitude() {
return longitude;
}
@OneToMany(mappedBy = "a")
@ContainedIn
private Set<AToB> multipleB = new HashSet<>();
}
@Entity
@Indexed
public class AToB {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
@ManyToOne
@IndexedEmbedded(includePaths = "location") // includePaths will be necessary to avoid infinite recursion if you really want an @IndexedEmbedded from A to B
private A a;
@ManyToOne
@IndexedEmbedded
private B b;
}
@Entity
public class B {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
@OneToMany(mappedBy = "b")
@ContainedIn
private Set<AToB> multipleA = new HashSet<>();
}
Then query like this:
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(AToB.class).get();
Query luceneQuery = qb.
spatial()
.onField("a.location")
.within(kmRadius, Unit.KM)
.ofLatitude(centerLatitude)
.andLongitude(centerLongitude)
.createQuery();
Upvotes: 2