Подтвердить что ты не робот

Как сделать 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
  • Обработка исключений
    • Показать пользователю сообщение об ошибке
    • Возможно, выполните более простой запрос, оставив ошибочный бит

У меня действительно нет отличных идей о том, как сделать любую из этих стратегий. Кто-нибудь еще затронул эту проблему? Есть ли "простые" или "изящные" парсеры, о которых я не знаю?

4b9b3361

Ответ 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, вы можете пойти лучше, написав собственный анализатор запросов. Это не так сложно, как может показаться на первый взгляд.