0

現在、Lucene/Solr のフィルターの指定に問題があります。私が思いつく解決策はすべて、他の解決策を壊します。例から始めましょう。次の 5 つのドキュメントがあるとします。

  • doc1 = [タイプ:車、販売:偽、所有者:ジョン]
  • doc2 = [タイプ: 自転車、商品 ID:1、所有者: ブライアン]
  • doc3 = [タイプ:車、販売:真、所有者:マイク]
  • doc4 = [タイプ: 自転車、商品 ID:2、所有者: ジョシュ]
  • doc5 = [タイプ:車、販売:偽、所有者:ジョン]

したがって、次のフィルター クエリを作成する必要があります。

  1. sales:false のみを持つ type:Car のすべてのドキュメントを教えてください。それが Car とは異なるタイプである場合は、結果に含めてください。したがって、基本的にはドキュメント 1、2、4、5 が必要です。不要なドキュメントは doc3 だけです。より正確に言えば:

    for each document d in solr/lucene
    if d.type == Car {
        if d.sold == false, then add to result
        else ignore
    }
    else {
        add to result
    }
    return result
    
  2. (type:Car and sold:false) または (type:Bike and productID:1) のすべてのドキュメントをフィルター処理します。したがって、これについては 1,2,5 を取得します。

  3. type:Car の場合は、sold:false でのみ取得するすべてのドキュメントを取得します。それ以外の場合は、所有者の John、Brian、Josh からドキュメントを取得します。したがって、このクエリでは、1、2、4、5 を取得する必要があります。

注:ドキュメント内のすべてのタイプを把握しているわけではありません。ここでは、ドキュメントの数が少ないため明らかです。

したがって、私の解決策は次のとおりです。

  1. (-type:Car) OR ((type:Car) AND (sold:false) これは正常に機能し、期待どおりに機能します。
  2. ((-type:Car) OR ((type:Car) AND (sold:false)) AND ((-type:Bike) OR ((type:Bike) AND (productID:1))) このソリューションは機能しません.
  3. ((owner:John) OR (owner:Brian) OR (owner:Josh)) AND ((-type:Car) OR ((type:Car) AND (sold:false)). これはうまくいきません。これを行うと機能します: ((所有者:ジョン) OR (所有者:ブライアン) OR (所有者:ジョシュ)) AND ((バージョン:* OR (-タイプ:車)) OR ((タイプ:車) AND (sold:false)). 論理的には機能するはずなので、これがどのように機能するのかわかりませんが、Solr/Lucene は何らかの形で機能します。
4

2 に答える 2

0

私のアドバイスは、解釈されるテキスト クエリを発行するのではなく、プログラムによる Lucene (つまり、Java Lucene API を使用して Java で直接) を使用することです。これにより、よりきめ細かい制御が可能になります。

これから行うことは、 QueryWrapperFilter APIを使用して Lucene フィルター オブジェクトを構築することです。QueryWrapperFilter は、Lucene クエリを受け取り、そのクエリに一致しないドキュメントを除外するフィルターです。

QueryWrapperFilter を使用するには、関心のある用語に一致する Query を作成する必要があります。これを行う最善の方法は、TermQueryを使用することです。

TermQuery tq = new TermQuery(new Term("fieldname", "value"));

ご想像のとおり、"fieldname" をフィールドの名前に置き換え、"value" を目的の値に置き換えます。たとえば、OPの例から、次のようなことをしたいかもしれませんnew Term("type", "Car").

これは単一の用語にのみ一致します。複数の TermQueries と、それらを組み合わせて単一のより大きなクエリを作成する方法が必要になります。これを行う最良の方法は、BooleanQueryを使用することです:

BooleanQuery bq = new BooleanQuery();
bq.add(tq, BooleanQuery.Occur.MUST);

bq.add必要なだけ何度でも呼び出すことができます- 持っている TermQuery ごとに 1 回です。2 番目の引数は、クエリの厳密度を指定します。MUSTサブクエリが表示される、SHOULD表示される、または表示される必要があることを指定できますNOT(これらはBooleanQuery.Occur列挙型の 3 つの値です)。

各サブクエリを追加すると、この BooleanQuery は、要求したドキュメントのみに一致する完全なクエリを表します。ただし、まだフィルターではありません。これを QueryWrapperFilter にフィードする必要があります。これにより、フィルター オブジェクトが返されます。

QueryWrapperFilter qwf = new QueryWrapperFilter(bq);

それはそれを行う必要があります。次に、そのフィルターによって許可されたドキュメントに対してのみクエリを実行する場合は、新しいクエリ ( と呼びますq) とフィルターを取得し、FilteredQuery を作成します。

FilteredQuery fq = new FilteredQuery(q, qwf);
于 2013-07-17T20:44:01.657 に答える