31

私は Lucene.net を使用していますが、API は同じであり、両方のプラットフォームに解決策があることを望んでいるため、.NET と Java の両方のバージョンについてこの質問にタグを付けています。

他の人がこの問題に取り組んでいると確信していますが、良い議論や例を見つけることができませんでした.

デフォルトでは、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 に送信する前に「クリーン」にする
  • 例外を適切に処理する
    • ユーザーにインテリジェントなエラー メッセージを表示する
    • おそらく、より単純なクエリを実行して、エラーのあるビットを除外します

これらの戦略をどのように実行するかについて、私は本当に素晴らしいアイデアを持っていません。他の誰かがこの問題に対処しましたか? 私が知らない「シンプル」または「優雅な」パーサーはありますか?

4

6 に答える 6

44

Yoは、次のようなクエリをサニタイズすることにより、Luceneに特殊文字を無視させることができます

query = QueryParser.Escape(query)

ユーザーにクエリで高度な構文を使用させたくない場合は、常にこれを行うことができます。

ユーザーに高度な構文を使用してもらいたいが、間違いを許容したい場合は、ParseException が発生した後にのみサニタイズする必要があります。

于 2008-11-05T12:57:27.330 に答える
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 の機能を利用することを本当に期待していない場合は、それが最善の策です。完全に (?) 堅牢になり、ユーザーはアナライザーを介して面白いキャラクターを検索できます。

于 2008-11-04T21:35:07.487 に答える
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;
}
于 2009-05-12T22:27:10.970 に答える
1

Lucene のすべての機能が必要ない場合は、独自のクエリ パーサーを作成することをお勧めします。そもそも見た目ほど複雑ではありません。

于 2008-11-05T12:59:58.557 に答える
1

私もあなたと同じ状況です。

これが私がすることです。私は例外をキャッチしますが、エラーをよりきれいに見せるためだけです。私はテキストを変更しません。

少し簡略化した Lucene 構文の説明へのリンクも提供します:
http://ifdefined.com/btnet/lucene_syntax.html

于 2008-11-04T20:03:33.990 に答える
1

Lucene.net についてはよくわかりません。一般的な Lucene については、本Lucene in Actionを強くお勧めします。当面の質問については、ユーザーによって異なります。使いやすさ、セキュリティ、パフォーマンスなど、ユーザーのクエリを制限する強力な理由があります。この本は、QueryParser の代わりにカスタム パーサーを使用してクエリを解析する方法を示しています。BooleanQuery に関する Jay のアイデアには賛成ですが、カスタム パーサーを使用してより強力なクエリを作成することもできます。

于 2008-11-05T12:37:32.813 に答える