2011-11-23 22 views
5

"a"と "b"という2つのフィールドでインデックスを検索したいと考えています。私は、Freud -- theories of psychologyのような検索を与えていると私は、次のクエリを実行したいと思います:ORを使用して2つのLuceneクエリを結合するにはどうすればよいですか?

(a="Freud" AND b="theories of psychology") OR (b="Freud" AND a="theories of psychology") 

は、私はこれをどのように行うのですか?これまでのところ、私はLuceneのはMultiFieldQueryParserを使用して2つの半分(firstHalfsecondHalf)を構築する必要があり、その後、私は

BooleanQuery combined = new BooleanQuery(); 
combined.add(firstHalf, BooleanClause.Occur.SHOULD); 
combined.add(secondHalf, BooleanClause.Occur.SHOULD); 

しかしcombinedでそれらを組み合わせてきただけで、「理論」は「心理学」を発見しない場合の結果が返されることを可能にします私は両方の用語を間違いなく望んでいます。 Luceneは「心理学の理論」を3つの単語に分割し、それらを個別にORと組み合わせるようです。これをどうやって防ぐのですか?

firstHalfは、次のようになります。analyzerはちょうどStandardAnalyzerオブジェクトです

Query firstHalf = MultiFieldQueryParser.parse(Version.LUCENE_33, 
     new String[]{"Freud", "theories of psychology"}, 
     new String[]{"a", "b"}, 
     new BooleanClause.Occur[]{BooleanClause.Occur.MUST, BooleanClause.Occur.MUST}, 
     analyzer); 

+0

はただのLuceneは次のようにブール論理をサポートしていないと言われた、それはSHOULD = OR!。その場合、_Lucene in Action_ 2版は95ページで間違っています。:)今私は_why_私のクエリが壊れていることを知っている、ちょうどそれを修正する方法を知らない。 – dmn

+0

クエリは正しいですか?クエリー「心理学の理論」とは、3つの単語のうちの少なくとも1つがどこかで出現しなければならないが、それらのどれもが必要な単語ではないことを意味する。 –

+0

@ KaiChanいいえ、私はこの制限を入れるためにこれを修正しなければなりませんでした。 :) – dmn

答えて

2

標準アナライザはトークン化します。したがって、クエリtheories of psychologytheories OR of OR psychologyに相当します。

フレーズ「心理学の理論」を検索したい場合はPhraseQueryを使用するか、あるいはデフォルトQueryParserフレーズを意味するものとして引用符を解釈することに注意してください(すなわち"\"theories of psychology\""であるためにあなたのコードを変更します)。

はい、Luceneがブール論理を使用していないという感覚がありますが、ここでは技術的ではなく、実際には関係ありません。

3

自分で考えましたが、コードはかなり長くなりました。より洗練されたソリューションを誰かが知っているなら、投稿してください。私は喜んで報酬を与えます。 :)(私はまもなくメソッドにこれを行うことになりますが...しかし、ここで何が起こっているかのフルバージョンがあります...)

QueryParser parser = new QueryParser(Version.LUCENE_33, "a", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query a_0 = parser.parse("Freud"); 
parser = new QueryParser(Version.LUCENE_33, "b", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query b_1 = parser.parse("theories of psychology"); 

BooleanQuery firstHalf = new BooleanQuery(); 
firstHalf.add(a_0, BooleanClause.Occur.MUST); 
firstHalf.add(b_1, BooleanClause.Occur.MUST); 

parser = new QueryParser(Version.LUCENE_33, "b", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query b_0 = parser.parse("Freud"); 
parser = new QueryParser(Version.LUCENE_33, "a", analyzer); 
parser.setDefaultOperator(QueryParser.AND_OPERATOR); 
Query a_1 = parser.parse("theories of psychology"); 

BooleanQuery secondHalf = new BooleanQuery(); 
secondHalf.add(b_0, BooleanClause.Occur.MUST); 
secondHalf.add(a_1, BooleanClause.Occur.MUST); 

BooleanQuery combined = new BooleanQuery(); 
combined.add(firstHalf, BooleanClause.Occur.SHOULD); 
combined.add(secondHalf, BooleanClause.Occur.SHOULD); 

SHOULDが、私はここにそれを必要とするように動作してオンにします。

+1

Luceneを学ぶにあたって、私はQueryParserを避けて、直接的な基礎となるQueryタイプからすべてをまとめようとするのが最近の経験です。あなたはLuceneをよりよく理解し、クエリの構文に気を取られることはありません。 Xodarapが言及しているように、ここで本当に欲しいのはPhraseQueryです。あなたが今持っているのは、正確なフレーズではなく、「心理学」の「理論」と書かれた順番や順番と一致します。 (実際には、StandardAnalyzerは "of"を除外します。したがって、PhraseQueryであっても正確なフレーズに一致しません...しかし、それは通常は受け入れられる検索の限界です。) – Jegschemesch

2

私は、以下のように、複数のフィールドにわたって用語を検索しなければならない連鎖ファジークエリを生成するクラスを作成しました。 複合クエリは、GetQuery()メソッドを呼び出すことで取得できます。

public class QueryParam 
{ 
    public string[] Fields { get; set; } 
    public string Term { get; set; } 

    private QueryParam _andOperandSuffix; 
    private QueryParam _orOperandSuffix; 

    private readonly BooleanQuery _indexerQuery = new BooleanQuery();   

    public QueryParam(string term, params string[] fields) 
    { 
     Term = term; 
     Fields = fields; 
    } 

    public QueryParam And(QueryParam queryParam) 
    { 
     _andOperandSuffix = queryParam; 
     return this; 
    } 

    public QueryParam Or(QueryParam queryParam) 
    { 
     _orOperandSuffix = queryParam; 
     return this; 
    } 

    public BooleanQuery GetQuery() 
    {    
     foreach (var field in Fields) 
      _indexerQuery.Add(new FuzzyQuery(new Term(field, Term)), Occur.SHOULD); 

     if (_andOperandSuffix != null) 
      _indexerQuery.Add(_andOperandSuffix.GetQuery(),Occur.MUST); 

     if (_orOperandSuffix != null) 
      _indexerQuery.Add(_orOperandSuffix.GetQuery(), Occur.SHOULD); 

     return _indexerQuery; 
    } 

} 

例:

var leftquery = new QueryParam("Freud", "a").And(new QueryParam("theories of psychology", "b")); 
var rightquery = new QueryParam("Freud", "b").And(new QueryParam("theories of psychology", "a")); 
var query = leftquery.Or(rightquery);    
関連する問題