如何让Lucene QueryParser更宽容?

时间:2008-11-04 19:30:22

标签: lucene lucene.net

我正在使用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之前“清理”查询
  • 优雅地处理异常
    • 向用户显示智能错误消息
    • 也许执行一个更简单的查询,不要使用错误的位

关于如何做这些策略,我真的没有什么好主意。还有其他人解决了这个问题吗?是否有任何我不了解的“简单”或“优雅”解析器?

6 个答案:

答案 0 :(得分:43)

哟可以通过使用像

这样的东西清理查询来使Lucene忽略特殊字符
query = QueryParser.Escape(query)

如果您不希望用户在查询中使用高级语法,则可以始终执行此操作。

如果您希望您的用户使用高级语法,但您也希望对错误更加宽容,那么您应该只在ParseException发生后进行清理。

答案 1 :(得分:8)

嗯,最简单的方法是给查询的原始形式一个镜头,如果失败了,就回去清理它。

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的功能,那将是最好的选择。你完全(?)健壮,用户可以通过你的分析器搜索任何有趣的角色

答案 2 :(得分:3)

仅供参考...这是我用于.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\.@-]", " ");
        q = qp.Parse(cooked);
    }

    return q;
}

答案 3 :(得分:1)

我和你的情况相同。

这就是我的工作。我确实捕获了异常,但只是为了让错误看起来更漂亮。我不会改变文字。

我还提供了一个链接到Lucene语法的解释,我已经简化了一点:
http://ifdefined.com/btnet/lucene_syntax.html

答案 4 :(得分:1)

我对Lucene.net了解不多。对于Lucene将军,我强烈推荐这本书Lucene in Action。对于手头的问题,这取决于您的用户。有很多原因,例如易用性,安全性和性能,限制用户的查询。本书介绍了使用自定义解析器而不是QueryParser解析查询的方法。我是第二个Jay关于BooleanQuery的想法,尽管你可以使用自定义解析器构建更强大的查询。

答案 5 :(得分:1)

如果您不需要所有Lucene功能,那么编写自己的查询解析器可能会更好。它并不像最初看起来那么复杂。