休眠搜索:用于空间查询的字段()未配置为空间字段

时间:2018-08-21 11:57:44

标签: hibernate-search hibernate-spatial

我有“组织”和“坐标”类。 坐标如下:

@Entity
@Table(name = "COORDINATES")
@Indexed
@Spatial
public class Coordinates implements Serializable {

private static final long serialVersionUID = 1L;

public Coordinates() {}

@Id
@Column(name = "id", nullable = false)
@SequenceGenerator(name = "generator", sequenceName = "COORDINATES_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
private Long id;

@Field
@Latitude
@Column(name = "LATITUDE", nullable = false)
private Double latitude;

@Field
@Longitude
@Column(name = "LONGITUDE", nullable = false)
private Double longitude;

我将注释@IndexedEmbedded放在组织的坐标字段中(即@Indexed + @Entity + @Table)。 为什么在我的查询中无法识别空间特征?我有以下例外:

  

org.hibernate.search.exception.SearchException:HSEARCH000131:   用于空间的字段“ organization.Organization#coordinates”   查询未配置为空间字段。检查正确使用   @Spatial分别位于SpatialFieldBridge   org.hibernate.search.query.dsl.impl.ConnectedSpatialQueryBuilder.createSpatialQuery(ConnectedSpatialQueryBuilder.java:63)   在   org.hibernate.search.query.dsl.impl.ConnectedSpatialQueryBuilder.createQuery(ConnectedSpatialQueryBuilder.java:38)


编辑1

我尝试在Spatial批注中添加名称,但出现错误,提示找不到@Latitude和@Longitude。 所以我尝试实现Hibernate的坐标,将@Entity更改为@Embeddable,将@Spatial的@IndexedEmbedded更改为Organization类中的@Spatial。 coordinates属性,在我的Coordinates类中删除@Latitude + @Longitude,覆盖getLatitude()getLongitude()。现在,我有以下异常:

  

org.hibernate.AnnotationException:@OneToOne或@ManyToOne   com。(...)。model.organization.organization.coordinates   引用未知实体:   com。(...)。model.localization.Coordinates

我正在使用:

  • 休眠核心:5.2.12。最终
  • hibernate-jpamodelgen:5.2.12.Final
  • hibernate-search-orm:5.8.2.Final
  • hibernate-search-elasticsearch:5.8.2.Final

我与其他开发人员进行了交谈,似乎他们需要在最新版本中进行了更改的功能,因此我们暂时不希望更改。

这是组织类中有趣的部分:

@Entity
@Table(name = "ORGANIZATION", uniqueConstraints = {@UniqueConstraint(columnNames = { "CODE" }) })
@Indexed
public class Organization implements Serializable, FileEntity {
    // lots of attributes, getters, setters, constructor
    @Spatial(name = "location", spatialMode = SpatialMode.RANGE)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "COORDINATES_ID")
    private Coordinates coordinates;
}

以及修改后的Coordinates类:

@Embeddable
@Table(name = "COORDINATES")
@Indexed
public class Coordinates implements org.hibernate.search.spatial.Coordinates, Serializable {
    // serial, constructor, id get+set
    @Field
    @Column(name = "LATITUDE", nullable = false)
    private Double latitude;

    @Field
    @Column(name = "LONGITUDE", nullable = false)
    private Double longitude;
    @Override
    public Double getLatitude() {
        return this.latitude;
    }

    @Override
    public Double getLongitude() {
        return this.longitude;
    }
}

编辑2

我在@Latitude和@Longitude中添加了“(of =“ location”)“。 我仍然有错误:

  

错误消息:   {“ root_cause”:[{“ type”:“ query_shard_exception”,“原因”:“失败   查找geo_point字段[coordinates.location]“(...)

也许它来自查询? 查询:

final BooleanJunction bool = queryBuilder.bool().must(queryBuilder.bool()                                                              
    .should(...)
    .should(...)
    .should(queryBuilder
        .spatial()
        .onField("coordinates.location")
        .within(12, Unit.KM)
        .ofLatitude(form.getLatitude())
        .andLongitude(form.getLongitude())
        .createQuery())
    .createQuery())
    .must(...)
    .must(...)
    .must(...);
final FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(bool.createQuery(), Organization.class);
fullTextQuery.setMaxResults(form.getMaximumNumberOfResult());
fullTextQuery.setProjection(FullTextQuery.SPATIAL_DISTANCE, FullTextQuery.THIS);
fullTextQuery.setSpatialParameters(form.getLatitude(), form.getLongitude(), "coordinates.location");
fullTextQuery.setProjection(FullTextQuery.THIS, FullTextQuery.SCORE);

Organization中的“ coordinates”字段为@IndexedEmbedded,而Coordinates类则与您编写时相同。

1 个答案:

答案 0 :(得分:0)

因此,首先,Hibernate Search设法从一开始就有点奇怪,因为您的映射包含一个错误:您应该在name注释上设置@Spatial属性。然后,Hibernate Search将使用该名称创建一个Coordinates类型的字段(假设为“ location”)。 完成此操作后,您将可以使用Organization名称从coordinates.location类型查询该字段。

我知道,在这种情况下听起来有点愚蠢,但是通常您在@Spatial注释上加上的实体是业务类型,而不是代表坐标的东西,因此更有意义。

另一种选择是将您的Coordinates类型变成可嵌入的而不是实体,使其实现org.hibernate.search.spatial.Coordinates,并将@Spatial批注放在Organization#coordinates属性上而不是放在Coordinates类型上。这样一来,您将不再需要@IndexedEmbedded@Latitude / @Longitude,并且实际上可以在查询时使用coordinates字段名称。

如果上述方法无效,请添加您正在使用的Hibernate Search和Hibernate ORM版本以及Organization类的代码。


编辑:为您的修改提供帮助...

关于找不到@Latitude / @Longitude批注:您需要使用这些批注的of属性来匹配您的字段名称。

如果您切换到@Embeddable,则会导致出现以下情况:

@Entity
@Table(name = "COORDINATES")
@Indexed
@Spatial(name = "location")
public class Coordinates implements Serializable {

private static final long serialVersionUID = 1L;

public Coordinates() {}

@Id
@Column(name = "id", nullable = false)
@SequenceGenerator(name = "generator", sequenceName = "COORDINATES_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
private Long id;

@Field
@Latitude(of = "location")
@Column(name = "LATITUDE", nullable = false)
private Double latitude;

@Field
@Longitude(of = "location")
@Column(name = "LONGITUDE", nullable = false)
private Double longitude;

}

关于切换到可嵌入对象后的“ org.hibernate.AnnotationException”:您需要删除@ManyToOne属性上的coordinates并将其替换为@Embedded。嵌入的属性与关联有很大的不同,请查看Hibernate ORM documentation