Почему мой Lucene.сбой сетевого поиска при выполнении нечеткого поиска по нескольким словам в поисковом запросе?

#lucene #lucene.net #fuzzy-search

#lucene #lucene.net #нечеткий поиск

Вопрос:

В моем приложении у меня есть компания с полем названия This is a test , которое правильно индексируется Lucene.Net. Для справки, для моего MultiFieldQueryParser оператора по умолчанию установлено значение QueryParser.Operator.AND .

Мой поиск завершается, когда я ищу this test~ и this tst~ . Однако мой поиск завершается неудачей, когда я пытаюсь выполнить поиск по this~ test~ , thas~ test~ , thas test~ и другим вариантам.

Вся цель состоит в том, чтобы позволить пользователю немного ошибиться в своем поиске, поэтому, если пользователь выполняет поиск по Jon Doe , он все равно покажет результаты для John Doe , позволяя пользователям не помнить точное написание того, что они ввели в базу данных. К сожалению, похоже, что он разрешает нечеткий поиск только по последнему термину в поисковой фразе. Я делаю что-то неправильно, или мне нужно использовать целый отдельный анализатор, чтобы сделать это?

Ответ №1:

Недавно мне пришлось реализовать нечто подобное в моем проекте.

В итоге я разделил фразу на несколько сегментов и построил запрос вручную.

 var input = "This is a test";

var fieldName = "yourField";
var minimumSimilarity = 0.5f;
var prefixLength = 3;
var query = new BooleanQuery();

var segments = input.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
foreach (var segment in segments)
{
    var term = new Term(fieldName, segment);
    var fuzzyQuery = new FuzzyQuery(term, minimumSimilarity, prefixLength);
    query.Add(fuzzyQuery, BooleanClause.Occur.SHOULD);
}
  

Я знаю, это очень примитивно, но, похоже, работает.

Примечание: это было протестировано только в Lucene.net v2.3.1.3

Комментарии:

1. Примечание: Это работает лучше всего, если вы используете анализатор пробелов во время индексации, многие другие анализаторы будут использовать данные в нижнем регистре, поэтому поиск по «Этому» ничего не соответствует.

2. В моем случае не требовалось, чтобы поиск учитывал регистр, поэтому я генерирую поиск Term с помощью StandardAnalyzer.TokenStream(string fieldName, TextReader reader)

3. Для Java это будет query.add(new BooleanClause(fuzzyQuery, Occur.SHOULD)) в последней строке