Поиск в спящем режиме: получение функциональности оператора SQL IN - PullRequest
0 голосов
/ 28 января 2019

Можно ли получить функциональность оператора SQL IN при создании запросов в поиске Hibernate?

Например, у меня есть эти два простых класса (конструкторы, геттеры и сеттеры опущены):

@Entity
@Indexed
public class Product {
    private long id;
    @Field
    private String title;
    @IndexedEmbedded
    private Category category;
}

@Entity
public class Category {
    private long id;
    @Field
    private String name;
}

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

org.apache.lucene.search.Query luceneQuery = queryBuilder
        .keyword()
        .onField("title")
        .matching(queryString)
        .createQuery();

Но я бы хотел искать товары по названию только в определенных категориях.Имея список идентификаторов (или имен) категорий для поиска, как я могу создать такой запрос?

Я нашел этот вопрос SO , но автор не нашелправильное решение.Может быть, сейчас такая функциональность уже существует?

Буду признателен за любую помощь.

1 Ответ

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

Сначала индексируйте id категорий:

@Entity
@Indexed
public class Product {
    private long id;
    @Field
    private String title;
    @IndexedEmbedded
    private Category category;
}

@Entity
public class Category {
    @Field // Added this
    private long id;
    @Field
    private String name;
}

Затем обязательно переиндексируйте данные, например, с помощью индексатора массы .

Затем,измените код запроса, как описано ниже.

Сначала вам понадобится SQL IN, который выражается в мире Lucene как category.id = <first> OR category.id = <second> OR ....Только логические операторы немного отличаются от того, к чему вы привыкли ( см. Здесь );в вашем случае вы хотите, чтобы «хотя бы одно» предложение совпадало, поэтому вам придется использовать оператор should:

List<Long> categoryIds = ...; // Provided by the user
BooleanJunction<?> categoryIdJunction = queryBuilder.bool();
for ( categoryId : categoryIds ) {
    categoryIdJunction.should(
        queryBuilder
            .keyword()
            .onField("category.id")
            .matching(categoryId)
            .createQuery();
    );
}
org.apache.lucene.search.Query categoryIdQuery = categoryIdJunction.createQuery();

Наконец, вам нужно будет объединить этот запрос с другим запросом наназвание.Для этого используйте другое логическое соединение, на этот раз с оператором must (все предложения должны совпадать):

org.apache.lucene.search.Query titleQuery = queryBuilder
        .keyword()
        .onField("title")
        .matching(queryString)
        .createQuery();
org.apache.lucene.search.Query luceneQuery = queryBuilder.bool()
        .must( categoryIdQuery )
        .must( titleQuery )
        .createQuery();
...