Как выполнить поиск с помощью дополнительных данных и перечислить данные в ElasticsearchRepository?

#java #spring-boot #elasticsearch #spring-data-elasticsearch

Вопрос:

Я использую spring-data-elasticsearch , и у меня есть следующий класс,

 @Document(indexName = "sample")
class Sample {

   @Id
   private String id;
   private String n_id;
   private String b_ref;
   private String r_ref;
   private Status status;
}
 

вышесказанное сохраняется до elasticsearch . И у меня есть следующий метод, чтобы найти в нем данные.

 List<Sample> getAll(String n_id, Optional<String> b_ref, Optional<String> r_ref, List<Status> statuses);
 

Но проблема, с которой я сталкиваюсь, заключается в том, что у меня есть 2 Optional поля и 1 List поле, которые нужно проверить, соответствует ли contains статус. Я перепробовал несколько способов, ElasticsearchRepository но ни один из них не сработал.

Как я могу построить запрос для описанного выше сценария?

Комментарии:

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

2. Да, поэтому при поиске, если Optional оно пустое, оно не должно учитывать это поле. Если поле Optional не пустое, то только оно должно выполнять поиск по этому полю вместе с другими полями.

3. Другой вопрос: все ли это свойства вашей сущности? С показанным кодом свойство id будет идентификатором, используемым в Elasticsearch, и вы никогда не получите обратно более одного документа, поскольку вы не можете хранить несколько документов с одним и тем же идентификатором.

4. О, на самом деле извините за путаницу. Я отредактировал вопрос. id является первичным ключом. И n_id это просто обычный идентификатор, который дублируется.

5. Наличие необязательного параметра в качестве аргумента часто считается запахом кода. Вы уже знаете, что вам нужно внести какие-то изменения, если опция пуста, поэтому лучше сказать об этом прямо. Смотрите, например, рецепт 15 в этой замечательной статье blogs.oracle.com/javamagazine/…

Ответ №1:

Вы можете реализовать это с помощью a CriteriaQuery ( operations является ElasticsearchOperations реализацией, введенной в ваш класс):

     List<Sample> getAll(String n_id, Optional<String> b_ref, Optional<String> r_ref, List<Status> statuses) {

        Criteria criteria = new Criteria("nid").is(n_id).and("status").in(statuses);

        if (b_ref.isPresent()) {
            criteria = criteria.and("b_ref").is(b_ref.get());
        }

        if (r_ref.isPresent()) {
            criteria = criteria.and("r_ref").is(r_ref.get());
        }

        SearchHits<Sample> searchHits = operations.search(new CriteriaQuery(criteria), Sample.class);

        // to only get the objects without hit information
        return searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
    }
 

Комментарии:

1. Большое вам спасибо за ваш ответ. А также спасибо вам за то, что уделили свое время ответу на этот вопрос.