使用空间搜索的 Hibernate 搜索 ManyToMany
Hibernate search ManyToMany with spatial search
我有一个带有 Hibernate Search @Spatial 数据的实体 A,如下所示:
@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<>();
}
实体 A 与实体 B 存在多对多关系。
实体 A 具有对实体 B 很重要的空间信息。现在我想对实体 B 执行空间查询,该查询使用实体 A 的位置信息。
@Entity
@Indexed
public class B {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
@ManyToMany
@ContainedIn
private Set<A> multipleA = new HashSet<>();
}
我尝试像这样对实体 B 进行查询:
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();
但是问题是,当我这样查询时,出现以下异常:
The field 'B#multipleA.location' used for the spatial query is not configured as spatial field. Check the proper use of @Spatial respectively SpatialFieldBridge.
有没有办法对类型 B 的实体进行空间查询,这些实体使用来自与 @ManyToMany 连接的实体 A 的空间数据?
对于我的查询,如果为每个连接的实体 A 多次返回相同的实体 B(就像连接一样),这也是可以接受的。
示例(a_1 是最接近的实体 A)
Database: b_1 -> (a_1, a_2), b_2 -> (a_1), b_3 -> (a_2, a_3)
查询结果:
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)
Hibernate Search 不支持多值位置;即使您设法对其建立索引,查询也无法正常工作(它将混合来自不同点的纬度和经度)。
如果您将多对多关联建模为一个实体,索引该实体并查询它而不是 B
。
另外,请注意您遇到的错误与另一个问题有关:您定位的字段不存在。如果你想让它存在,你需要在 B#multipleA
.
上添加一个 @IndexedEmbedded
下面是应该更好用的东西:
@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<>();
}
然后这样查询:
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();
我有一个带有 Hibernate Search @Spatial 数据的实体 A,如下所示:
@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<>();
}
实体 A 与实体 B 存在多对多关系。 实体 A 具有对实体 B 很重要的空间信息。现在我想对实体 B 执行空间查询,该查询使用实体 A 的位置信息。
@Entity
@Indexed
public class B {
@Id
@GeneratedValue(generator = "uuid2")
private UUID id;
@ManyToMany
@ContainedIn
private Set<A> multipleA = new HashSet<>();
}
我尝试像这样对实体 B 进行查询:
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();
但是问题是,当我这样查询时,出现以下异常:
The field 'B#multipleA.location' used for the spatial query is not configured as spatial field. Check the proper use of @Spatial respectively SpatialFieldBridge.
有没有办法对类型 B 的实体进行空间查询,这些实体使用来自与 @ManyToMany 连接的实体 A 的空间数据?
对于我的查询,如果为每个连接的实体 A 多次返回相同的实体 B(就像连接一样),这也是可以接受的。
示例(a_1 是最接近的实体 A)
Database: b_1 -> (a_1, a_2), b_2 -> (a_1), b_3 -> (a_2, a_3)
查询结果:
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)
Hibernate Search 不支持多值位置;即使您设法对其建立索引,查询也无法正常工作(它将混合来自不同点的纬度和经度)。
如果您将多对多关联建模为一个实体,索引该实体并查询它而不是 B
。
另外,请注意您遇到的错误与另一个问题有关:您定位的字段不存在。如果你想让它存在,你需要在 B#multipleA
.
@IndexedEmbedded
下面是应该更好用的东西:
@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<>();
}
然后这样查询:
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();