Спящий поиск Lucene. Предложение, но почти как SQL "LIKE" - PullRequest
0 голосов
/ 07 марта 2019

Это мой первый раз, когда я имею дело с оптимизированной функциональностью поиска, и часть моего опыта находится на переднем крае разработки под Android, но я готов принять приключение поиска в спящем режиме.Я понимаю функциональность SQL-запроса «LIKE», что он делает и его ограничения, вот почему я сразу перешел к hibernate-search (lucene), моя цель - сделать автоматическое предложение на основе входных данных (входных запросов),Это то, что я получил до сих пор

@Indexed
@Table (name = "shop_table")
@Entity
@AnalyzerDef(name = "myanalyzer",
    tokenizer = @TokenizerDef(factory = KeywordTokenizerFactory.class), //
    filters = { //
            @TokenFilterDef(factory = LowerCaseFilterFactory.class),
            @TokenFilterDef(factory = WordDelimiterFilterFactory.class),
            @TokenFilterDef(factory = EdgeNGramFilterFactory.class, params = 
{ @Parameter(name = "maxGramSize", value = "1024") }),})
@Analyzer(definition = "myanalyzer")
public class Shop implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
enter code here

@Field(index = Index.YES, store = Store.YES, analyze = Analyze.YES)
@Column(name = "name")
private String name;

... other methods

Мой запрос

 Query lucenQuery = qb.keyword().onField("name").matching(searchTerm).createQuery();

Это просто базовый запрос, и я сосредоточен исключительно на конфигурации анализатора, чтобы получить то, чтоЯ хочу, это действительно сбивает с толку, на какой части я должен сосредоточиться, чтобы достигнуть того, чего я хочу, Tokenizing?Фильтрация?или сам запрос?в любом случае, я уже проиндексировал эти 2 фразы.

"Apache Lychee Department" 
"Apache Strawberry Club Large"

Когда я обрабатываю / запрашиваю "Солома", он дает мне Apache Strawberry Club Large , но когда я обрабатываю / запрашиваю "Личи"или" Apache Lychee"запрос дает мне оба?Я только ожидаю, что Apache Lychee Department

То, как я понимаю, все мои настройки: / 10 *

EdgeNGramFilterFactory (1024) даст мне серию1024 индекса EdgeNGrams

LowerCaseFilterFactory даст мне все индексы в нижнем регистре

WordDelimiterFilterFactory отфильтруйте его, сделав запрос одним словом, и дайтемне соответствующие данные.

и каждая запись / данные будут маркированы как ключевое слово KeywordTokenizerFactory и будут проиндексированы 1024 EdgeNGram

Я пытался запросить фразу,но все равно получаю тот же результат

  Query luceneQuery = qb.phrase().onField("name").sentence(searchTerm).createQuery();

Моя цель - иметь самовнушение ... или, по крайней мере, начать с имитации "LIKE" sql ..

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

Я сделал так, благодаря @ yrodiere

@Indexed
@Table (name = "shop_table")
@Entity
@AnalyzerDef(name = "edgeNgram",
    tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
    filters = {
            @TokenFilterDef(factory = LowerCaseFilterFactory.class),
            @TokenFilterDef(factory = EdgeNGramFilterFactory.class, params = 
                                      { @Parameter(name = "maxGramSize", value = "1024") }),
    })
@AnalyzerDef(name = "search_query_analyzer",
    tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
    filters = {
            @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
            @TokenFilterDef(factory = LowerCaseFilterFactory.class)
    })
public class Shop implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


@Field(store = Store.YES, analyze = Analyze.YES)
@Column(name = "name")
@Analyzer(definition = "edgeNgram")
private String name;

public void setName(String name) {
    this.name = name;
}

public String getName() {
    return this.name;
}
}

и мой запрос

  QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Shop.class)
            .overridesForField("name", "search_query_analyzer").get();

    Query lucenQuery = qb.simpleQueryString().onField("name").withAndAsDefaultOperator().matching(shopSearchTerm).createQuery();

Но я не уверен, правильно ли я это внедряю ..

0 голосов
/ 08 марта 2019

Необходимо учитывать две вещи:

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

Это означает, в частности,что ваш запрос "Lychee" будет проанализирован на что-то вроде "L Ly Lyc Lych Lyche Lychee" (из-за фильтра ngram ребра).Строка "Apache Strawberry Club Large" была предварительно проанализирована, а термин "Large" был расширен до "L La Lar Larg Large" из-за фильтра граничной диаграммы.Таким образом, запрос «Lychee» будет соответствовать «Apache Strawberry Club Large» просто потому, что оба они содержат слово, начинающееся с L ...

Это явно нежелательное поведение.

Первый шаг будетизменить способ анализа вашего запроса, чтобы в конечном итоге вы не совпали с совершенно не связанными документами.По сути, вам нужно определить другой анализатор, который почти идентичен, но не имеет фильтра "edge ngram".Затем вам нужно будет указать Hibernate Search использовать этот анализатор для анализа вашего запроса.

Подробное объяснение см. в этом ответе .

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

Заменить это:

Query lucenQuery = qb.keyword().onField("name").matching(searchTerm).createQuery();

этим:

Query lucenQuery = qb.simpleQueryString().onField("name").withAndAsDefaultOperator().matching(searchTerm).createQuery();

Ключом является вызов .withAndAsDefaultOperator().

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

...