Поиск в спящем режиме: поиск и сортировка в одном поле - PullRequest
0 голосов
/ 14 марта 2019

Я использую hibernate-поиск 5.11.1, и мне нужно поддерживать поиск и сортировку в одном поле типа String. Прочитав справочное руководство , я нашел следующую документацию по использованию нормализаторов для сортировки анализируемого текста.

Справка из официального руководства:

Анализаторы хороши, когда вам нужно искать в текстовых документах, но Что делать, если вы хотите отсортировать анализируемый текст? Тогда вы немного проблемы, потому что анализируемый текст является многозначным: при индексации книга под названием «Рефакторинг: улучшение дизайна существующих Код », анализируемый заголовок фактически является (неупорядоченным) набором {"рефакторинг", "улучшение", "дизайн", "существующий", "код"}. если ты пытался отсортировать по названию после такого анализа любое из этих слов может быть использован, так что ваша книга может оказаться в D (из-за «дизайн»), или в R (из-за «рефакторинга»), или в E, и т.д.

Итак, в конце концов, вы, вероятно, не хотите, чтобы ваши поля были токенизированы когда вы сортируете по этим полям. Нормализаторы решают именно эту проблему: они анализаторы, но без токенизатора и с некоторым временем выполнения проверки, которые мешают анализу производить несколько токенов, тем самым гарантируя, что ваши сорта всегда будут последовательными.

Hibernate Search обеспечивает эквивалент нормализатора для соответствующего анализатора аннотации: @Normalizer, @NormalizerDef, @NormalizerDefs. Как с анализатор, вы можете использовать реализации напрямую (например, @Normalizer (impl = MyCollactionKeyAnalyzer.class)) или именованный нормализаторы (например, @Normalizer (definition = "myNormalizer") с @NormalizerDef (filters = @TokenFilterDef (factory = LowerCaseFilterFactory.class)).

Исходя из вышеизложенного, я написал следующий код:

@Entity
@Indexed
@AnalyzerDef(name = "en", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
        filters = {
                @TokenFilterDef(factory = LowerCaseFilterFactory.class),
                @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class)
        })
@NormalizerDef(name = "lowercase", filters = {
                @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
                @TokenFilterDef(factory = LowerCaseFilterFactory.class)
        }
)
@Table(name = "ORDER")
public class Order {

    //Some other fields that are omitted for brevity here

    @Field(name = "orderName_Search", store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "en"))
    @Field(name = "orderName_Sort", store = Store.YES, analyze = Analyze.NO, normalizer = @Normalizer(definition = "lowercase"))
    @SortableField(forField = "orderName_Sort")
    @Column(name = "ORDER_NAME")
    private String orderName;

}

Однако, похоже, он не работает, так как я столкнулся со следующей ошибкой.

[ОШИБКА] com.appnexus.konnect.web.exceptions.ConnectExceptionHandler - Исключение org.hibernate.search.exception.SearchException: невозможно автоматически определить тип поля для поля 'orderName'. Используйте byField (String, Sort.Type), чтобы явно указать тип сортировки

Мой вопрос: где это пошло не так? Работает только при использовании аннотации @Field, но не при использовании обоих.

1 Ответ

1 голос
/ 14 марта 2019

Из сообщения об ошибке кажется, что вы написали что-то вроде этого:

qb.sort().byField("orderName").createSort()

Но поле orderName не существует в отношении поиска в спящем режиме. Существуют только orderName_Search и orderName_Sort. В этом случае вы должны написать:

qb.sort().byField("orderName_Sort").createSort()

Также имейте в виду, что установка analyze = Analyze.NO на orderName_Sort эффективно отключит ваш нормализатор. Вы, вероятно, хотите оставить это.

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