Токенайзер пробелов не работает при использовании простой строки запроса - PullRequest
0 голосов
/ 10 апреля 2019

Я впервые реализовал поиск запросов с использованием SimpleQueryString, показанного следующим образом.

Определение сущности

@Entity
@Indexed
@AnalyzerDef(name = "whitespace", tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
    filters = {
        @TokenFilterDef(factory = LowerCaseFilterFactory.class),
        @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class)
    })

public class AdAccount implements SearchableEntity, Serializable {

    @Id
    @DocumentId
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Field(store = Store.YES, analyzer = @Analyzer(definition = "whitespace"))
    @Column(name = "NAME")
    private String name;

    //other properties and getters/setters
}

Я здесь использую фабрику токенизатора пробелов, потому что стандартный анализатор по умолчаниюигнорирует специальные символы, что не идеально в моем случае использования.Документ, на который я ссылался, - https://lucene.apache.org/solr/guide/6_6/tokenizers.html#Tokenizers-WhiteSpaceTokenizer.. В этом документе говорится, что простой токенизатор разбивает текстовый поток на пробельные символы и возвращает последовательности непробельных символов в виде токенов.

Метод SimpleQueryString

protected Query inputFilterBuilder() {
    SimpleQueryStringMatchingContext simpleQueryStringMatchingContext = queryBuilder.simpleQueryString().onField("name");

    return simpleQueryStringMatchingContext
        .withAndAsDefaultOperator()
        .matching(searchRequest.getQuery() + "*").createQuery();
}

searchRequest.getQuery () возвращает строку поискового запроса, затем я добавляю префиксный оператор в конце, чтобы он поддерживал префиксный запрос.

Однако в следующем примере это работает не так, как ожидалось.Скажем, у меня есть объект с именем «Учетная запись AT & T», при поиске с помощью «AT &» он не возвращает этот объект.

Затем я внес следующие изменения, чтобы напрямую использовать анализатор пробелов.На этот раз поиск с «AT &» работает как положено.Но поиск теперь чувствителен к регистру, то есть поиск с помощью at & сейчас ничего не возвращает.

@Field
@Analyzer(impl = WhitespaceAnalyzer.class)
@Column(name = "NAME")
private String name;

Мои вопросы:

  1. Почему это не работает, когда я использую фабрику пустого пространства в первой попытке?Я предполагаю, что использование фабрики по сравнению с использованием фактической реализации анализатора отличается?

  2. Как сделать мой поиск без учета регистра, если я использую аннотацию @Analyzer, как и во второй попытке?

1 Ответ

0 голосов
/ 15 апреля 2019

Почему это не работает, когда я использую фабрику пустого пространства в первой попытке? Я предполагаю, что использование фабрики по сравнению с использованием фактической реализации анализатора отличается?

Запросы с подстановочными знаками и префиксами (те, которые вы используете при добавлении суффикса * в строку запроса), никогда не применяют анализ. Это означает, что ваш строчный фильтр не применяется к вашему поисковому запросу, но он был применен к вашему проиндексированному тексту, что означает, что он никогда не будет совпадать: AT&* не соответствует индексированному at&t.

Использование аннотации @Analyzer работало только потому, что вы удалили нижний регистр во время индекса. С этим анализатором вы получили индекс AT&T (в верхнем регистре), а AT&* соответствует индексируемому AT&T. Это просто случайно: если вы индексируете At&t, вы в конечном итоге получите At&t в индексе и у вас будет та же проблема.

Как сделать мой поиск нечувствительным к регистру, если я использую аннотацию @Analyzer, как во второй попытке?

Как я упоминал выше, аннотация @Analyzer не является решением, вы фактически ухудшили свой поиск.

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

Вы можете восстановить исходный анализатор и выполнить запрос в нижнем регистре самостоятельно, но это только поможет вам: ascii fold и другие функции анализа не будут работать.

Решением, которое я обычно рекомендую, является использование фильтра ребер-нграмм. Идея состоит в том, чтобы индексировать каждый префикс каждого слова, чтобы «Учетная запись AT & T» была проиндексирована как термины a, at, at&, at&t, a, ac, acc, acco, accou, accoun, account, а поиск по «at &» вернул бы правильные результаты даже без подстановочного знака.

См. этот ответ для более подробного объяснения.

Если вы используете интеграцию ELasticsearch, вам придется полагаться на хак, чтобы заставить анализатор «только для запросов» работать правильно. Смотрите здесь .

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