Мы использовали Lucene.NET в течение нескольких лет для поиска текста, извлеченного из файлов, на основе пользовательского ввода условий поиска. Тем не менее, мы недавно столкнулись с проблемой, о которой сообщается клиентом, где поиск терминов с несколькими косыми чертами не возвращает совпадений.Запрос Lucene.NET с несколькими косыми чертами
Примером может служить индексное значение SB/ABC/1234-123
, а пользователь вводит SB/*
для соответствия всем документам с этим префиксом. Однако на основе этого запроса результаты не возвращаются. Нечетная часть заключается в том, что поиск ABC/*
действительно возвращает документ со значением SB/ABC/1234-123
, полностью игнорируя компонент SB/
.
Изначально проблема была сообщили с комбинацией прямого слэша и шаблона (SB/*
не возвращать спички для SB/1234-123
), но это было адресовано, используя QueryParser
с KeywordAnalyzer
в дополнение к предыдущему QueryParser
с только StandardAnalyzer
.
Здесь используется текущий код (упрощенный для ключевых элементов, которые могут воспроизвести проблему).
var reader = IndexReader.Open(FSDirectory.Open(new DirectoryInfo(indexPath)), true);
var searcher = new IndexSearcher(reader);
var mainQuery = new BooleanQuery();
// The analyzer and parser for searching the index fields with full stop-words and tokenizers
var fieldAnalyzer = new StandardAnalyzer(LuceneVersion);
var fieldParser = new MultiFieldQueryParser(LuceneVersion, reader.GetFieldNames(IndexReader.FieldOption.ALL).ToArray(), fieldAnalyzer);
// The analyzer and parser for searching the index fields using no stop words or tokenizers
var fieldKeywordAnalyzer = new KeywordAnalyzer();
var fieldKeywordParser = new MultiFieldQueryParser(LuceneVersion, reader.GetFieldNames(IndexReader.FieldOption.ALL).ToArray(), fieldKeywordAnalyzer);
// Build and append the Standard and Keyword query clauses together for the whole field value query to pick up all relevant results
var fieldQuery = fieldParser.Parse(textCriteria);
var fieldKeywordQuery = fieldKeywordParser.Parse(textCriteria);
var fieldBooleanQuery = new BooleanQuery
{
{fieldQuery, Occur.SHOULD},
{fieldKeywordQuery, Occur.SHOULD}
};
mainQuery.Add(fieldBooleanQuery, Occur.MUST);
var hits = searcher.Search(mainQuery, reader.NumDocs());
Фактическая разобранный запрос в пределах mainQuery
в момент вызова searcher.Search
+((Title:sb/abc/*) (Title:sb/abc/*))
. В этом случае оба предложения BooleanQuery
оказываются одинаковыми. Инструмент Люк обычно используется для работы с индексами Lucene кажется, думает, что это недопустимый синтаксис при использовании KeywordAnalyzer
(игнорируя токенизированный аспект на данный момент):
Cannot parse '+((Title:sb/abc/*) (Title:sb/abc/*))': '*' or '?' not allowed as first character in WildcardQuery.
Мое предположение, что имея два слеша является заставляя его рассматривать его как регулярное выражение. Вопрос в том, как мы получим, чтобы он правильно соответствовал результатам и не рассматривал его как регулярное выражение. Выключение косых черт в критериях поиска не изменило обработанный запрос, увиденный выше, или возвращенные результаты.
Наше текущее требование состоит в том, что оно должно поддерживать поиск токенизированных/стоп-слов (для текстовых фраз и т. Д.), А также точные соответствия (мы храним много номеров счетов и т. Д., Которые не должны быть обозначены) на тех же самых полях одновременно и обе управляющие символы. Запрос SB/*
является примером поиска подстановочных знаков по сценарию с точным соответствием.
Надеюсь, это имеет смысл. При необходимости я могу добавить дополнительное разъяснение.
Редактировать: Наши данные организованы в ряд столбцов, которые могут хранить любое текстовое значение. Пример: некоторые клиенты помещают значение, которое является уникальным значением/идентификатором (номер счета и т. Д.) В поле 1 для doctype A. Тот же клиент может использовать поле 1 в виде текстового блока (полное имя и т. Д.) Для doctype B. Doctypes классификации документов, которые описывают на высоком уровне, что конкретный документ должен представлять, например, счет-фактура, в PO и т.д. Пример данных:
DocId DocType Field1 Field2 Field3, etc
1234 A SB/2567 John Doe
5678 B Jane Doe 90210
3456 A ABC/5678 Bobby Lee
StandardAnalyzer обрабатывает ваш пример номер счета SB/ABC/1234-123 как две лексемы: [сб] [а/1234-123]. Вот почему «ABC/*» соответствует. –
Вот почему мы также добавили KeywordAnalyzer, чтобы он просматривал как токенированные (стандартные) значения, так и не-токенизированные (ключевое слово). В этом сценарии, похоже, игнорируется KeywordAnalyzer. – Kettch19
@ DanielBrixen Извините, не пометил вас в своем ответе, и он не позволит мне его редактировать. – Kettch19