Поисковые данные Elasticsearch находят по полю и по последней дате запроса - PullRequest
0 голосов
/ 08 июля 2019

Я использую Spring Boot 2.1.6 и Elasticsearch 6.2.2

РЕДАКТИРОВАТЬ, чтобы лучше прояснить мой вопрос :

Когда я позволил Spring сгенерировать запрос для меняиспользуя следующий метод в моем репозитории:

Account findTop1ByAccountIdOrderByCreatedDesc(final String accountId);

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

Но у меня есть только две записи в индексе, идентичные минус дата создания, и этот запрос возвращает оба результата.Я думаю, это означает, что это не соответствует тому, что я имею в виду, а скорее выберет все учетные записи с этим идентификатором (так как это ключ, все они «верхние»), в порядке убывания.

Это будет болееточно соответствует моему запросу, но это не является допустимым наименованием:

Account findTop1OrderByCreatedDescByAccountId(final String accountId);

org.springframework.data.mapping.PropertyReferenceException: No property descByAccountId found for type LocalDateTime! Traversed path: Account.created.

И этот также:

Account findTop1OrderByCreatedDescAndAccountIdEquals(final String accountId);

org.springframework.data.mapping.PropertyReferenceException: No property desc found for type LocalDateTime! Traversed path: Account.created.

Итак, как мне перевести, если вообще возможно, мой запрос наМагия весеннего хранилища?

/ EDIT

Оригинальный вопрос:

У меня есть POJO, объявленный как таковой (урезанный вариант):

@Document(indexName = "config.account", type = "account")
public class Account{

    @Id
    private String id;

    @Field(type = FieldType.Text)
    @JsonProperty("ilmAccountIdentifier")
    private String accountId;

    @Field(type = FieldType.Text)
    private String endOfBusinessDay;

    @Field(type = FieldType.Date)
    private LocalDateTime created;

}

И я хотел бы запросить индекс, чтобы получить самую последнюю запись (созданную = max) для данного accountId.

Я знаю, что могу использовать построитель запросов, но мне было интересно, есть ли какие-томагия, которая делает это для меня, используя пружинные именованные запросы, в настоящее время я пытался (не смог найти другую допустимую комбинацию формулировок):

Account findTop1ByAccountIdOrderByCreatedDesc(final String accountId);

Но он возвращает ноль.Я вижу данные в индексе (усеченная версия):

Account(id=W83u0GsBEjwDhWt1-Whn,
accountId=testfindByAccountIdReturnsLatestVersion,
endOfBusinessDay=17:00:00,
created=2019-07-08T09:34)

Но сгенерированный Spring запрос довольно странный и не тот, который я ожидал:

SearchRequest{
searchType=QUERY_THEN_FETCH,
indices=[config.account],
indicesOptions=IndicesOptions[ignore_unavailable=false, allow_no_indices=true, expand_wildcards_open=true, expand_wildcards_closed=false, allow_aliases_to_multiple_indices=true, forbid_closed_indices=true, ignore_aliases=false],
types=[account],
routing='null',
preference='null',
requestCache=null,
scroll=null,
maxConcurrentShardRequests=0,
batchedReduceSize=512,
preFilterShardSize=128,
allowPartialSearchResults=null,
source={
  "from":0,
  "query":{
    "bool":{
      "must":[{
        "query_string": 
          {"query":
             "testfindByAccountIdReturnsLatestVersion",
             "fields": ["accountId^1.0"],
             "type":"best_fields",
             "default_operator":"and",
             "max_determinized_states":10000,
             "enable_position_increments":true,
             "fuzziness":"AUTO",
             "fuzzy_prefix_length":0,
             "fuzzy_max_expansions":50,
             "phrase_slop":0,
             "escape":false,
             "auto_generate_synonyms_phrase_query":true,
             "fuzzy_transpositions":true,
             "boost":1.0}
          }],
        "adjust_pure_negative":true,"boost":1.0}
      }
,"version":true}}

Что бы я хотелвместо этого эквивалент этого SQL-запроса:

select *
from(
  select *
  from account
  where accountId = ?
  order by created desc
)
where rownum = 1

Можно ли вообще что-то делать с магией Spring или я должен использовать QueryBuilder или свою собственную логику для него?

Спасибо и ура

EDIT

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

@Repository
public interface AccountRepository  extends ElasticsearchRepository<Account, String>, AccountRepositoryCustom {

    List<Account> findByIlmAccountIdentifierOrderByCreatedDesc(final String accountId);

}

public interface AccountRepositoryCustom {

    Account findLatestByAccountId(final String accountId);

}

@Repository
public class AccountRepositoryImpl implements AccountRepositoryCustom {

    @Autowired
    @Lazy
    private AccountRepository accountRepository;

    public Account findLatestByAccountId(final String accountId){
        return accountRepository.findByIlmAccountIdentifierOrderByCreatedDesc(accountId).get(0);
    }

}

1 Ответ

1 голос
/ 13 июля 2019

Для запросов, построенных из имен методов, вы должны использовать имена свойств из вашего класса Document, поэтому здесь findByAccountId является правильным.

Проблема действительно заключается в переименовании этого свойства в индексе с аннотацией @JsonProperty. Эта аннотация использовалась для записи отображения в индекс, и, насколько я помню, при записи данных с классами Template, но не с классами Repository. Таким образом, запрос репозитория ищет поле accountId в индексе, тогда как данные хранятся в поле ilmAccountIdentifier .

В версии 3.2.0 Spring Data Elasticsearch (в настоящее время RC1, RC2 выйдет в конце этого месяца, а GA должен выйти в начале сентября) имеется новая реализация Mapper, с которой он работает без @JsonProperty просто используя аннотацию @Field:

@Field(name="ilmAccountIdentifier", type = FieldType.Text)
private String accountId;

Но 3.2.x не будет работать с Elasticsearch 6.2, вам нужно будет обновить до 6.7.

В качестве обходного пути, вы можете переименовать свойство accountId в ilmAccountIdentifier?

Редактировать 23.07.2019:

Я только что обнаружил, что ограничение результата с topN не работает - это старая ошибка в Spring Data Elasticsearch, кажется, она никогда не была реализована в этом подмодуле. Поэтому, пожалуйста, проголосуйте за этот вопрос.

Примечание: spring-data -asticsearch - это модуль сообщества, поэтому мы живем за счет вкладов!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...