web-dev-qa-db-ja.com

QueryParserを使用して、特殊文字を含むLuceneクエリを実行する方法は?

ここにあるものです。 '-'などの特殊文字を含む用語がインデックスに格納されています。最も単純なコードは次のとおりです。

Document doc = new Document();
doc.add(new TextField("message", "1111-2222-3333", Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.addDocument(doc);

次に、次のように、QueryParserを使用してクエリを作成します。

String queryStr = "1111-2222-3333";
QueryParser parser = new QueryParser(Version.LUCENE_36, "message", new StandardAnalyzer(Version.LUCENE_36));
Query q = parser.parse(queryStr);

そして、サーチャーを使用してクエリを検索しても結果が得られません。私もこれを試しました:

Query q = parser.parse(QueryParser.escape(queryStr));

そして、まだ結果はありません。

QueryParserを使用せずに、代わりにTermQueryを直接使用すると、私が望むことを実行できますが、この方法は、ユーザー入力テキストに対して十分な柔軟性を備えていません。

おそらく、StandardAnalyzerがクエリ文字列の特殊文字を省略するために何かをしたと思います。デバッグを試みたところ、文字列が分割されており、実際のクエリは次のようになっています。 "message:1111 message:2222 message:3333"。 luceneが正確に何をしたのかわかりません...

それで、特殊文字でクエリを実行したい場合、どうすればよいですか?アナライザーを書き換えるか、デフォルトのものからqueryparserを継承する必要がありますか?そして、どのように?...

更新:

1 @The New Idiot @femtoRgon、問題に記載されているようにQueryParser.escape(queryStr)を試しましたが、それでも機能しません。

2問題を解決する別の方法を試しました。 TokenizerからTokenTokenizerを派生させ、Wordをスペースでのみ切り、Analyzerから派生したQueryAnalyzerにパックし、最後にQueryAnalyzerをQueryParserに渡しました。

今では動作します。元々は、デフォルトのStandardAnalyzerがデフォルトのルール(一部の特殊文字をスプリッターとして認識する)に従ってqueryStrをカットするため機能しません。クエリがQueryParserに渡されると、特殊文字はStandardAnalyzerによってすでに削除されています。今私はqueryStrをカットするために独自の方法を使用し、それはスペースをスプリッターとしてのみ認識するため、特殊文字は処理を待っているクエリに残り、これは機能します。

3 @The New Idiot @femtoRgon、私の質問に答えてくれてありがとう。

22
Yuanchao Tang

これについてはわかりませんが、エスケープする必要があると思います-\Lucene docs のとおり。

「-」または禁止演算子は、「-」記号の後の用語を含むドキュメントを除外します。

もう一度、

Luceneは、クエリ構文の一部である特殊文字のエスケープをサポートしています。現在のリストの特殊文字は

+-&& || ! (){} [] ^ "〜*?:\ /

これらの文字をエスケープするには、文字の前に\を使用します。

また、Javaで特別な意味を持つ場合、2回エスケープする必要がある文字も覚えておいてください。

22
NINCOMPOOP

addまたはaddTextの代わりにaddValue()として値を追加できます。次に、Standard Analyzerではなく、KyewordAnalyzerを使用して特殊文字を検索します。またはaddValue()を使用してデータを追加し、lukeでデータを検索しているときに、特殊文字をワイルドカード検索文字(?)に置き換えます。私は両方の方法を試してみました

0
Shrek