Spring data elasticsearch, как создать метод репозитория для поля ключевого слова

Допустим, у меня есть такое сопоставление, и я хочу выполнить поиск по полю «requestId.keyword», чтобы получить запросы на точное соответствие. Как я могу реализовать это с репозиторием Spring Data Elasticsearch без использования аннотации @Query?

 "requestId": {
      "type": "text",
      "analyzer": "1_to_15_analyzer_without_space",
      "search_analyzer": "all_symbols_and_fold_analyzer",
      "fields": {
        "keyword": {
          "type": "keyword"
        }
      }
    }
0
0
35
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это невозможно с механизмом построения запросов путем самоанализа имени метода. Первая идея состоит в том, чтобы иметь что-то вроде (здесь я использую сущность Foo):

SearchHits<Foo> searchByRequestId_Keyword(String keyword);

Анализ имени метода выполняется в модуле spring-data-common, который использует только имена свойств Java-свойств объекта (могут быть вложенными). Но подполе ключевое слово существует только в Elasticsearch и — если не создано автоматически — в аннотации @MultiField. Но код для анализа имени метода не использует информацию, специфичную для хранилища, поэтому такой подход не будет работать и завершится ошибкой, что keyword не является свойством text, что правильно для объекта Java.

Что вы можете сделать, так это сначала добавить пользовательский интерфейс фрагмента репозитория:

public interface FooKeywordRepository {
    SearchHits<Foo> searchByRequestIdKeyword(String keyword);
}

и предоставьте реализацию, которая должна называться как интерфейс с суффиксом Внедрение:

import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;

public class FooKeywordRepositoryImpl implements FooKeywordRepository {

    private final ElasticsearchOperations operations;

    public FooKeywordRepositoryImpl(ElasticsearchOperations operations) {
        this.operations = operations;
    }

    @Override
    public SearchHits<Foo> searchByRequestIdKeyword(String keyword) {

        Query query1 = new NativeSearchQueryBuilder()
            .withQuery(QueryBuilders.termQuery("requestId.keyword", keyword))
            .build();

        Query query2 = new CriteriaQuery(Criteria.where("requestId.keyword").is(keyword));

        return operations.search(query1, Foo.class); // could be query2 as well
    }
}

У вас есть инъекция ElasticsearchOperations, и вы используете ее для выполнения запроса, который вы создаете. Я указал два способа построения запроса, оба работают.

Ваше определение репозитория для использования будет таким:

public interface FooRepository extends ElasticsearchRepository<Foo, String>, FooKeywordRepository {
    // other custom methods if needed
}

Другие вопросы по теме