Lucene.Net поиск по нескольким терминам по нескольким полям, которые существуют в документе - PullRequest
0 голосов
/ 18 января 2019

Я использую образец PAF-файла Royal Mail, эти данные были импортированы в базу данных, а следующие поля проиндексированы с помощью моего собственного консольного приложения Lucene indexer:

...

var doc = new Document();

doc.Add(new Field("id", item.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("postcode", item.Postcode, Field.Store.YES, Field.Index.ANALYZED));
doc.Add(new Field("buildingname", item.BuildingName, Field.Store.YES, Field.Index.ANALYZED));

...

То, что я хочу сейчас сделать, это предоставить либо частичный, либо полный почтовый индекс или имя здания, и получить совпадения, если в каждом поле документов в каждом из полей почтового индекса или имени здания встречается свободный поиск. Так что, если почтовый индекс / название здания был:

TE55 5TT Test Building

Если бы я предоставил "TE55 Test", я бы ожидал, что он вернется.

Мой поисковый код

var fieldsToAnalyse = new[] { "postcode", "buildingname" };

var finalQuery = new BooleanQuery();
var parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_29, fieldsToAnalyse, _analyzer);

string[] terms = searchTerm.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);

foreach (string term in terms)
{
    var formattedTerm = term.Replace("~", "");

    var formattedTermWildcard = $"+{formattedTerm}~";

    finalQuery.Add(parser.Parse(formattedTermWildcard), Occur.MUST);

}

var searcher = new IndexSearcher(_indexDirectory, true);

var hits = searcher.Search(finalQuery,10);

foreach (var hit in hits.ScoreDocs)
{
    documents.Add(searcher.Doc(hit.Doc));
}

_analyzer.Close();
searcher.Dispose();
return documents;

Что на самом деле происходит.

значение finalQuery равно:

{+ (+ (почтовый индекс: тест ~ 0.5 Building Name: тест ~ 0.5)) + (+ (почтовый индекс: te55 ~ 0.5 buildingname: te55 ~ 0,5))}

Я получаю обратные адреса, которые имеют почтовый индекс, содержащий «te55», но buildingname пусто. Мне нужно, чтобы оба имели почтовый индекс, содержащий «te55», а название здания - «test».

Sidenote

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

System.IndexOutOfRangeException: 'Индекс находился за пределами массив.

Что меня тоже озадачило

1 Ответ

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

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

В качестве напоминания - логический синтаксис Lucene следующий:

+ must clause
<empty> should clause
- not clause

В вашем случае у вас есть

postcode:te55~0.5 buildingname:te55~0.5

, который запрашивает совпадение как минимум один, но не форсирует обоих .

У вас должен быть такой запрос:

+postcode:te55~0.5 +buildingname:te55~0.5

Основная проблема в MultiFieldQueryParser заключается в том, что по умолчанию он создает предложения must. Вам нужно setDefaultOperator(AND_OPERATOR) раньше, чтобы получить желаемое поведение.

Некоторая информация, связанная с Lucene.Net 3.0.3 - https://lucenenet.apache.org/docs/3.0.3/d6/d0b/class_lucene_1_1_net_1_1_query_parsers_1_1_multi_field_query_parser.html

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