8

ユーザーがLucene3.5で複数のフィールドを検索できるようにするために、現在、検索する各フィールドのQueryParserを作成してDisjunctionMaxQueryに追加しています。これは、デフォルトの演算子としてORを使用する場合にうまく機能しますが、より正確な(そしてより少ない)結果を得るために、デフォルトの演算子をANDに変更したいと思います。

問題は、queryParser.setDefaultOperator(QueryParser.AND_OPERATOR)すべての用語が少なくとも1つのフィールドに含まれている必要があるため、多くのドキュメントを見逃すことです。

たとえば、ドキュメントの次のデータについて考えてみます。titleフィールド= "Programming Languages"、bodyフィールド= "Java、C ++、PHP"。ユーザーがJavaプログラミングを検索した場合、この特定のドキュメントは結果に含まれません。これは、タイトルまたは本文フィールドにクエリ内のすべての用語が含まれているためです。上記のクエリではこのドキュメントを返したいのですが、HTMLプログラミングのクエリでは返しません。

キャッチオールフィールドを検討しましたが、いくつか問題があります。まず、ユーザーはクエリ(author:bill)にフィールドごとの用語を含めることがよくありますが、これはキャッチオールフィールドでは不可能です。また、FastVectorHighlighterを使用して特定のフィールドを強調表示します。これには、インデックスを付けて保存する必要があります。したがって、キャッチオールフィールドを追加すると、同じデータのほとんどを2回インデックス付けする必要があり、時間とスペースが消費されます。

何か案は?

4

3 に答える 3

7

もう少し調べておくべきだったと思います。MultiFieldQueryParserは、私が探していた正確な機能を提供することがわかりました。何らかの理由で、次のように検索したいフィールドごとにQueryParserを作成していました。

String[] fields = {"title", "body", "subject", "author"};
QueryParser[] parsers = new QueryParser[fields.length];      
for(int i = 0; i < parsers.length; i++)
{
   parsers[i] = new QueryParser(Version.LUCENE_35, fields[i], analyzer);
   parsers[i].setDefaultOperator(QueryParser.AND_OPERATOR);
}

これにより、次のようなクエリが生成されます。

(+title:java +title:programming) | (+body:java +body:programming)

...これは私が探していたものではありません。次に、次のような単一のMultiFieldQueryParserを作成します。

MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_35, new String[]{"title", "body", "subject"}, analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);

これは私が探していたクエリを私に与えます:

+(title:java body:java) +(title:programming body:programming)

助けてくれた@seetaと@femtoRgonに感謝します!

于 2012-12-17T22:10:05.117 に答える
2

おそらく必要なのは、フィールドと用語のさまざまな組み合わせをキャプチャするブールクエリの組み合わせです。与えられた例では、クエリは次のようになります-

(title:Java AND body:programming)OR(title:programming AND body:Java)。

これを自動的に生成する既存のQueryクラスがあるかどうかはわかりませんが、それがインデックスで実行される最終的なクエリになるはずだと思います。

于 2012-12-17T02:41:12.330 に答える
0

同じ用語のセットで複数のフィールドを検索できるようにしたい場合は、コメントからの質問:

((title:java title:programming) | (body:java body:programming))~0.2

最良の実装ではない可能性があります。

タイトルからのスコア、または用語の組み合わせセットの本文からのスコアのいずれかを効果的に取得しています。タイトルでjavaをヒットし、本文でプログラミングを行う場合は、約 本体のJavaのヒットと同等の重みで、プログラミングのヒットはありません。

より構造化されたクエリは次のようになると思います。

(title:java body:java)~0.2 (title:programming body:programming)~0.2

これは私にとってより理にかなっています。なぜなら、同じ用語の複数のクエリ(異なるフィールド)でのスコアの増加をdismaxクエリで制限したいのですが、異なる用語でのヒットのスコアを増加させたいからです。

この種のクエリ構造でより良いスコア結果が得られる場合は、結果を特定の最小スコア(単純なハードコードされた値ではなく、返される最大スコアのパーセンテージ)に制限することで、弱すぎる結果が表示されないようにすることができます。


また、allフィールドのインデックス作成もカウントしません。これは私が以前に使用した実装であり、特定のフィールドとキャッチオールフィールドの両方にインデックスを付けるため、一般的なクエリと特定の単一フィールドクエリの両方が可能になります。インデックスストレージは、保存されていない用語に対してかなり無駄がない傾向があり、インデックスストレージがないことを補うために大きくて複雑なクエリを作成する必要がある場合は、一般的にパフォーマンスに役立ちます。

最小限のストレージしか必要としない場合は、そのフィールドのTermVectorsをオフにすることもできます。

new Field(name, value, Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO);

それが実際にどれほどの違いを生むかはわかりませんが。

于 2012-12-17T07:50:29.150 に答える