Запрос диапазона дат не возвращает никаких результатов поиска в спящем режиме сластиком поиска - PullRequest
0 голосов
/ 25 января 2019

Поиск в Hibernate не возвращает никаких результатов, когда мы используем запросы в диапазоне дат в наши проиндексированные даты.

Все остальные запросы диапазона работают как ожидалось

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

У нас есть другие запросы по диапазону веса, роста и т. Д., Которые работают как положено.

Изучая индекс с Люком, кажется, что даты проиндексированы, как и ожидалось.

У нас есть следующие доменные объекты, просто показывающие соответствующие поля

@Indexed
public class Person{

      @IndexedEmbedded
      @OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
      @Cascade({org.hibernate.annotations.CascadeType.PERSIST})
      private Set<DateOfBirth> datesOfBirth = new HashSet<>();
}

public class DateOfBirth{

     @Basic
     @Field
     @DateBridge(resolution = Resolution.MILLISECOND)
     @Column(name = "date_of_birth")
     private Date dateOfBirth;
}

Я также попробовал следующее в поле dateOfBirth

@Basic
@Field(bridge = @FieldBridge( impl = ElasticsearchDateBridge.class))
@Column(name = "date_of_birth")
@JsonFormat(pattern = "dd/MM/yyyy")
private Date dateOfBirth;

У нас есть следующий код для добавления в наш запрос, который предназначен для поиска всех людей в возрасте, переданном из пользовательского интерфейса

public void withAgeRange(Integer lowerAge, Integer upperAge){

    if(lowerAge != null || upperAge != null){

        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime lowerLocalDateTime = localDateTime.withYear(localDateTime.getYear() - upperAge);
        LocalDateTime upperLocalDateTime = localDateTime.withYear(localDateTime.getYear() - lowerAge);

        Date lowerDate = Date.from(lowerLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
        Date upperDate = Date.from(upperLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());

        bool.must(getQueryBuilder().range().onField("datesOfBirth.dateOfBirth").from(lowerDate).to(upperDate).createQuery());
    }
}

Изучение запроса до его выполнения показывает

+dateOfBirths.dateOfBirth:[33590595604 TO 1106595795604]

Глядя на пример документа с Люком, есть человек с датой рождения с индексированным значением 320976000000, который находится между нижней и верхней границей диапазона.

Соответствующий раздел Персонального картирования из Кибаны

      "datesOfBirth": {
        "properties": {
          "currentDateOfBirth": {
            "type": "boolean"
          },
          "dateOfBirth": {
            "type": "date",
            "store": true
          }
        }
      },

Как уже упоминалось ранее, все остальные наши запросы диапазона работают как ожидалось.

Мы ожидаем, что будет возвращен хотя бы один человек, но независимо от того, в каком диапазоне мы пытаемся, мы всегда получим 0 результатов.

Любые идеи будут с благодарностью.

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Получается, если мы аннотируем

@Basic
@Field(bridge = @FieldBridge( impl = ElasticsearchDateBridge.class))
@Column(name = "date_of_birth")
@JsonFormat(pattern = "dd/MM/yyyy")  
private Date dateOfBirth;

И измените запрос на

      bool.must(getQueryBuilder().range().onField("datesOfBirth.dateOfBirth").ignoreFieldBridge().from(dateFormat.format(lowerDate)).to(dateFormat.format(upperDate)).createQuery());

Где dateFormat

 DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

Работает как положено.

Не уверен, что это лучший подход. Или есть лучший способ сделать это?

Кажется, это немного грязно.

0 голосов
/ 26 января 2019

Похоже, это может быть проблемой с часовыми поясами ...

Похоже, вы храните данные с помощью java.util.Date. По моему опыту, это не передает информацию о часовых поясах Elasticsearch. Elasticsearch хранит даты внутри, используя UTC . Если часовой пояс пройден, ES преобразует его в UTC, когда он фактически сохраняет его. Если часовой пояс не пройден, ES будет считать, что ваша дата UTC, как есть.

Что это означает: если вы работаете в часовом поясе WEST США (GMT-8), это означает, что ES подумает , что вы хотели, чтобы ваша дата была за 8 часов до того, как вы ее передали быть. Например, если вы укажете дату рождения «01/25/19: 12: 00: 00», ES будет относиться к ней как таковой в UTC, которая на самом деле является «01/25/19: 4: 00: 00» вашей время. Это означает, что любые запросы, которые вы пытаетесь выполнить, должны быть скорректированы на -8 часов в зависимости от способа индексации документов в данный момент. Судя по вашему коду, вы настраиваете запросы для учета вашего часового пояса, но это может быть не так при фактической индексации.

Почему все остальные ваши запросы работают так, как ожидалось, но не этот, я не уверен, но моя догадка такова.

Чтобы обойти проблемы с датами, я индексирую документы с использованием ZonedDateTime в UTC.

Для справки: вот вопрос и последующий ответ, как только я его выяснил, который я опубликовал, когда имел дело с похожими проблемами: Запрос на получение меток времени, которые были обновлены более 30 минут назад, не работает

...