Поиск в спящем режиме: поле (), используемое для пространственного запроса, не настроено как пространственное поле

У меня есть классы Организация и Координаты. Координаты следующие:

@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 # координаты», используемое для пространственного запроса, не настроено как пространственное поле. Проверьте правильность использования @Spatial, соответственно, SpatialFieldBridge в org.hibernate.search.query.dsl.impl.ConnectedSpatialQueryBuilder.createSpatialQuery (ConnectedSpatialQueryBuilder.java:63) в org.hibernate.search.query.ConnectedSpatialQuery .java: 38)


Редактировать 1

Я попытался добавить имя к пространственной аннотации, но получил сообщение об ошибке: @Latitude и @Longitude не удалось найти. Итак, я попытался реализовать координаты Hibernate, изменив @Entity на @Embeddable, изменив @IndexedEmbedded для @Spatial в классе Organization в атрибуте coordinates, удалив @Latitude + @Longitude в моем классе координат, переопределив getLatitude() и getLongitude(). Теперь у меня следующее исключение:

org.hibernate.AnnotationException: @OneToOne или @ManyToOne на com. (...). model.organization.Organization.coordinates ссылается на неизвестный объект: com. (...). model.localization.Coordinates

Я использую :

  • спящее ядро: 5.2.12.Final
  • hibernate-jpamodelgen: 5.2.12.Final
  • hibernate-search-orm: 5.8.2.Финал
  • hibernate-search-elasticsearch: 5.8.2.Финал

Я разговаривал с другими разработчиками, и мне кажется, что им нужны функции, которые изменились в более поздних версиях, поэтому мы не хотим ничего менять в данный момент.

Вот интересная часть в классе организации:

@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

Я добавил "(of =" location ")" в @Latitude и @Longitude. У меня все еще есть ошибка:

Сообщение об ошибке: {"root_cause": [{"type": "query_shard_exception", "reason": "не удалось найти поле geo_point [координаты.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 - это @IndexedEmbedded, а класс Coordinates такой, как вы его написали.


person Marie    schedule 21.08.2018    source источник


Ответы (1)


Итак, во-первых, немного странно, что Hibernate Search удалось запустить с самого начала, потому что ваше сопоставление содержит ошибку: вы должны установить атрибут name в аннотации @Spatial. Затем Hibernate Search создаст поле типа Coordinates с этим именем (скажем, «местоположение»). Как только это будет сделано, вы сможете запрашивать это поле из типа Organization, используя имя coordinates.location.

Я знаю, в данном случае это звучит немного глупо, но обычно объект, на который вы помещаете аннотацию @Spatial, является бизнес-типом, а не чем-то, представляющим координаты, поэтому это имеет больше смысла.

Другой вариант - превратить ваш тип Coordinates во встраиваемый вместо сущности, заставить его реализовывать org.hibernate.search.spatial.Coordinates и поместить аннотацию @Spatial в свойство Organization#coordinates вместо того, чтобы помещать его в тип Coordinates. Тогда вам больше не понадобятся ни @IndexedEmbedded, ни _13 _ / _ 14_, и вы можете просто использовать имя поля coordinates при запросе.

Если вышеуказанное не работает, добавьте версии Hibernate Search и Hibernate ORM, которые вы используете, и код класса Organization.


РЕДАКТИРОВАТЬ: в ответ на ваше изменение ...

О том, что аннотации _17 _ / _ 18_ не найдены: вам нужно использовать атрибут 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.

person yrodiere    schedule 22.08.2018
comment
Спасибо за подсказки. Я отредактировал свой вопрос, чтобы ответить на ваш, так как вроде не получается. - person Marie; 22.08.2018
comment
@Marie Я добавил решения проблем, упомянутых в вашей редакции. - person yrodiere; 27.08.2018
comment
Отредактировал снова. Понятия не имею, почему это не работает. Кстати, спасибо за помощь. - person Marie; 28.08.2018
comment
@Marie, я вижу, вы используете интеграцию с Elasticsearch. Вам следует повторно генерировать схему Elasticsearch всякий раз, когда вы меняете сопоставление поиска Hibernate, иначе Elasticsearch не будет работать правильно. См. стратегии управления схемами в документация В процессе разработки я бы порекомендовал drop-and-create, особенно если вы можете легко переиндексировать все свои данные при запуске. - person yrodiere; 29.08.2018
comment
Да, мы используем функцию drop-and-create - person Marie; 29.08.2018