Как сделать Lucene QueryParser более прощающим?
Я использую Lucene.net, но помечаю этот вопрос как для версий .NET, так и для Java, потому что API тот же, и я надеюсь, что на обеих платформах есть решения.
Я уверен, что другие люди решили эту проблему, но мне не удалось найти хороших дискуссий или примеров.
По умолчанию Lucene очень придирчив к синтаксису запроса. Например, я просто получил следующую ошибку:
[ParseException: Cannot parse 'hi there!': Encountered "<EOF>" at line 1, column 9.
Was expecting one of:
"(" ...
"*" ...
<QUOTED> ...
<TERM> ...
<PREFIXTERM> ...
<WILDTERM> ...
"[" ...
"{" ...
<NUMBER> ...
]
Lucene.Net.QueryParsers.QueryParser.Parse(String query) +239
Каков наилучший способ предотвратить ParseExceptions при обработке запросов от пользователей? Мне кажется, что наиболее удобный интерфейс поиска - это тот, который всегда выполняет запрос, даже если это может быть неправильный запрос.
Кажется, что существует несколько возможных и дополнительных стратегий:
- "Очистить" запрос до его отправки в QueryProcessor
- Обработка исключений
- Показать пользователю сообщение об ошибке
- Возможно, выполните более простой запрос, оставив ошибочный бит
У меня действительно нет отличных идей о том, как сделать любую из этих стратегий. Кто-нибудь еще затронул эту проблему? Есть ли "простые" или "изящные" парсеры, о которых я не знаю?
Ответы
Ответ 1
Yo может заставить Lucene игнорировать специальные символы, дезактивируя запрос с помощью чего-то вроде
query = QueryParser.Escape(query)
Если вы не хотите, чтобы ваши пользователи когда-либо использовали расширенный синтаксис в своих запросах, вы можете делать это всегда.
Если вы хотите, чтобы ваши пользователи использовали расширенный синтаксис, но вы также хотите быть более прощающими с ошибками, вам нужно только санировать после возникновения ParseException.
Ответ 2
Ну, проще всего было бы сделать необработанную форму запроса выстрелом, и если это не удастся, вернитесь к его очистке.
Query safe_query_parser(QueryParser qp, String raw_query)
throws ParseException
{
Query q;
try {
q = qp.parse(raw_query);
} catch(ParseException e) {
q = null;
}
if(q==null)
{
String cooked;
// consider changing this "" to " "
cooked = raw_query.replaceAll("[^\w\s]","");
q = qp.parse(cooked);
}
return q;
}
Это дает необработанной форме пользовательского запроса возможность запуска, но если синтаксический анализ не удается, мы лишим все, кроме букв, цифр, пробелов и подчеркиваний; то мы попробуем еще раз. Мы все еще рискуем выбросить ParseException, но мы резко снизили шансы.
Вы также можете рассмотреть вопрос о том, как выполнять пользовательский запрос самостоятельно, превращая каждый токен в запрос терминов и объединяя их вместе с BooleanQuery. Если вы не ожидаете, что ваши пользователи смогут воспользоваться преимуществами QueryParser, это будет лучшим выбором. Вы были бы полностью (?) Надежны, и пользователи могли бы искать любые смешные персонажи, которые будут проходить через ваш анализатор
Ответ 3
FYI... Вот код, который я использую для .NET.
private Query GetSafeQuery(QueryParser qp, String query)
{
Query q;
try
{
q = qp.Parse(query);
}
catch(Lucene.Net.QueryParsers.ParseException e)
{
q = null;
}
if(q==null)
{
string cooked;
cooked = Regex.Replace(query, @"[^\w\[email protected]]", " ");
q = qp.Parse(cooked);
}
return q;
}
Ответ 4
Я в той же ситуации, что и вы.
Вот что я делаю. Я поймаю исключение, но только для того, чтобы я мог сделать ошибку более красивой. Я не изменяю текст.
Я также предоставляю ссылку на объяснение синтаксиса Lucene, который я немного упростил:
http://ifdefined.com/btnet/lucene_syntax.html
Ответ 5
Я не знаю много о Lucene.net. Для генерального Lucene я настоятельно рекомендую книгу Lucene in Action. Что касается вопроса, это зависит от ваших пользователей. Существуют сильные причины, такие как простота использования, безопасность и производительность, чтобы ограничить запросы пользователей. В книге показаны способы анализа запросов с использованием настраиваемого анализатора вместо QueryParser. Вторая идея Jay о BooleanQuery, хотя вы можете создавать более сильные запросы, используя собственный парсер.
Ответ 6
Если вам не нужны все функции Lucene, вы можете пойти лучше, написав собственный анализатор запросов. Это не так сложно, как может показаться на первый взгляд.