Spring ElasticSearch: Проблема при объединении нескольких запросов

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

Вопрос:

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

У меня есть простой API Spring boot, который позволяет студентам добавлять свои проекты в колледже. Эти проекты хранятся в ES, которые я пытаюсь сделать доступными для поиска.

FWIW, В примере использования POV пользователь может искать проект с помощью строки запроса, основанной на имени проекта или хэштеге для проекта, т. е. «Java».

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

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

Кто-нибудь может определить, что я делаю не так?

Большое спасибо

  private Iterable<UserProjects> searchCollegeProjects(Integer page, Integer size, List<String> hashtags, List<String> studentUserIds) {
        PageRequest pageRequest = PageRequest.of(page, size);
        QueryBuilder projectQueryBuilder = null;
        if (hashtags != null) {
            projectQueryBuilder =
                    QueryBuilders
                            .multiMatchQuery(hashtags.toString(), "projectName", "projectHashtag")
                            .fuzziness(Fuzziness.AUTO);
        }
        
        BoolQueryBuilder userIdQueryBuilder = null;
        if(studentUserIds!=null) {
            userIdQueryBuilder = QueryBuilders.boolQuery()
                    .must(QueryBuilders.termsQuery("userId.keyword", studentUserIds));
        }

        Query searchQuery = new NativeSearchQueryBuilder()
                .withQuery(projectQueryBuilder)
                .withQuery(userIdQueryBuilder)
                .withFilter(boolQuery()
                        .mustNot(QueryBuilders.termsQuery("isDraft", true)))
                .withPageable(PageRequest.of(page, size))
                .build();
        SearchHits<UserProjects> projectHits;
        try {
            projectHits =
                    elasticsearchOperations
                            .search(searchQuery, UserProjects.class,
                                    IndexCoordinates.of(elasticProjectsIndex));
        } catch (Exception ex) {
            logger.error("Error unable to perform search query"   ex);
            throw new GeneralSearchException(ex.toString());
        }
        List<UserProjects> projectMatches = new ArrayList<>();
        projectHits.forEach(srchHit -> {
            projectMatches.add(srchHit.getContent());
        });


        long totalCount = projectHits.getTotalHits();
        Page<UserProjects> resultPage = PageableExecutionUtils.getPage(
                projectMatches,
                pageRequest,
                () -> totalCount);
        return resultPage;
    }
 

Также ниже приведен мой POJO для пользовательских проектов:

 
@Getter
@Setter
@Document(indexName = "college.userprojects")
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserProjects {

    @Id
    @Field(type = FieldType.Auto, name ="_id")
    private String projectId;

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

    @Field(type = FieldType.Text, analyzer = "autocomplete_index", searchAnalyzer = "lowercase" ,name = "projectName")
    private String projectName;

    @Field(type = FieldType.Auto, name = "projectHashTag")
    private List<String> projectHashTag;

    @Field(type = FieldType.Boolean, name = "isDraft")
    private Boolean isDraft;

}
 

EDIT: Just to be clear, if I remove this line from the native query:

                 .withQuery(userIdQueryBuilder)
 

Я возвращаю проекты (правильно), которые содержат текст запроса в полях Имя проекта или Хэштег проекта. Если вставить приведенную выше строку обратно, поиск вернет все.