2012-04-23 10 views
7

私はクエリインターフェイスのand()およびor()メソッドを組み合わせて、2つの条件リストとそれぞれからの1つの条件セットを作成しようとしました満足しなければならない。モルフィアでの複雑なAND-ORクエリ

私はthis discussionを読み、2つの$または句を組み合わせるためにQuery.and()を使用しようとしています。

基本的に、私が言うことをしようとしている:

Criteria[] arrayA; 
Criteria[] arrayB; 

// Programatically populate both arrays 

Query q = dao.createQuery().and(
    q.or(arrayA), 
    q.or(arrayB) 
); 

私は基準の配列を使用しています、私は私が必要とする特定の基準を生成するために、いくつかの異なる入力をループしていて、ときに私、このアプローチは動作しますので、私はちょうど1つの$またはを使用していますが、私はMorphiaに$と$の両方を含めようとするときに私が期待するクエリを生成することができません。私は、2回目の呼び出しがあったかのように、$とクエリがなく、2番目の$が上書きされていることがわかります。

例:私は、クエリは次のように生成されることを期待:

{ 
    "$and": { 
    "0": { 
     "$or": { 
      "0": //Some criteria, 
      "1": //Some criteria, 
      "2": //Some criteria, 
     } 
    }, 
    "1": { 
     "$or": { 
      "0": //Some other criteria, 
      "1": //Some other criteria, 
      "2": //Some other criteria, 
     } 
    } 
} 

しかし、私はちょうどこのようなクエリを取得:

{ 
    "$or": { 
     "0": //Some other criteria, 
     "1": //Some other criteria, 
     "2": //Some other criteria, 
    } 
} 

が、私は多くのドキュメントを参照してください、しかし、見てすることはできませんテストケースでは、これはこれを行う正しい方法と思われます。誰も私が期待しているようにこれがなぜ機能していないのかを知る手助けができますか?

(私は最高の応答を得ることになるところはよく分からないので、この質問は、cross-posted to the Morphia mailing listた)

編集0

アップデート:この再訪、私はMorphiaのテストコードをチェックアウトしましたすべてが正常に動作し、テストコードで問題を再現できませんでした。

したがって、私は私が望むクエリの実例を試してみるために新しいプロジェクトを作成しました。しかし、ベアボーンのテストプロジェクトでも同じ問題が発生しました。 、私にとって

import java.net.UnknownHostException; 
import java.util.HashMap; 
import java.util.Map; 

import com.google.code.morphia.Datastore; 
import com.google.code.morphia.Morphia; 
import com.google.code.morphia.query.Query; 
import com.google.code.morphia.query.QueryImpl; 
import com.mongodb.Mongo; 
import com.mongodb.MongoException; 

public class Test { 

    static Mongo mongo; 
    static Morphia m; 
    static Datastore ds; 

    static { 
     mongo = null; 
     try { 
      mongo = new Mongo(); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (MongoException e) { 
      e.printStackTrace(); 
     } 
     m = new Morphia(); 
     ds = m.createDatastore(mongo, "test"); 
    } 

    public static void main(String[] args) { 
     populate(); 
     query(); 
    } 

    public static void query() { 
     Query<TestEntity> q = ds.createQuery(TestEntity.class); 

     q.and(q.or(q.criteria("map.field1").exists()), 
       q.or(q.criteria("map.field2").exists())); 

     Iterable<TestEntity> i = q.fetch(); 
     for (TestEntity e : i) { 
      System.out.println("Result= " + e.map); 
     } 

     QueryImpl<TestEntity> qi = (QueryImpl<TestEntity>) q; 
     System.out  
       .println("Query= " +   qi.prepareCursor().getQuery().toString()); 
    } 

    public static void populate() { 
     TestEntity e = new TestEntity(); 
     Map<String, Integer> map = new HashMap<String, Integer>(); 
     map.put("field1", 1); 
     map.put("field2", 2); 
     e.map = map; 

     ds.save(e); 
    } 
} 

プロジェクトがmavenisedされ、POMは次のとおりです。

import java.util.Map; 

import com.google.code.morphia.annotations.Entity; 

@Entity 
public class TestEntity { 
    Map<String, Integer> map; 
} 

そして最後に私のテストクラス:私はTestEntityクラスを持っている

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
<modelVersion>4.0.0</modelVersion> 
<groupId>test</groupId> 
<artifactId>test</artifactId> 
<version>0.0.1-SNAPSHOT</version> 
<name>Test</name> 


<dependencies> 
    <dependency> 
     <groupId>com.google.code.morphia</groupId> 
     <artifactId>morphia</artifactId> 
     <version>0.99</version> 
    </dependency> 
</dependencies> 
<dependencyManagement> 
    <dependencies> 
     <!-- Force the use of the latest java mongoDB driver --> 
     <dependency> 
      <groupId>org.mongodb</groupId> 
      <artifactId>mongo-java-driver</artifactId> 
      <version>2.7.3</version> 
     </dependency> 
    </dependencies> 
</dependencyManagement> 

</project> 

上記のコードは正しい$とクエリを生成しませんが、私は理由がわかりません

答えて

6

含むMorphia 150にもかかわらず、これは(二つの文にそれを壊す)私のために働くようですQuery.and(Criteria ...)メソッドでは、正しいクエリが生成されません。明示的な$とクエリで句をサポートして対処し

Issue 338は、Mavenの経由SNAPSHOT版として、現在のみ利用可能ですMorphia 0.99.1、対象としています。

はしかし、0.99.1-SNAPSHOTを使用すると、私たちのために、問題を解決しました。残念なことに

+1

の問題が解決され、最終的な実例が得られました。 –

+0

こんにちは@RussBateman、コードは変更されませんでした。バージョン0.99では0.99.1-SNAPSHOTで解決されている問題があるようですので、使用しているライブラリのバージョンを単純に変更しました。 – chrisbunney

+0

0.99.1-SNAPSHOTでも、私はまだQuery.and()に問題があります。基準が単純なフィールドであれば問題ありませんが、$やcriterialが$に含まれていれば失敗します。 –

7

ジャスト(テストする時間がありません)推測が、それはする必要があります:あなたは正しい

Query q = dao.createQuery().and(
    q.or(q.criteria(arrayA)), 
    q.or(q.criteria(arrayB)) 
); 

更新、Query.criteriaは右ではなかった - それは簡単なテストで使用したものでした私はあなたが何かを見逃していたと思った。

Query q = dao.createQuery(); 
q.and(
    q.or(arrayA), 
    q.or(arrayB) 
); 

アップデート2より完全なテストコード:

Criteria[] arrayA = {dao.createQuery().criteria("test").equal(1), dao.createQuery().criteria("test").equal(3)}; 
Criteria[] arrayB = {dao.createQuery().criteria("test").equal(2), dao.createQuery().criteria("test").equal(4)};; 
Query q = dao.createQuery(); 
q.and(
    q.or(arrayA), 
    q.or(arrayB) 
); 
System.out.println(q.toString()); 

が与える:

{ "$and" : [ { "$or" : [ { "test" : 1} , { "test" : 3}]} , { "$or" : [ { "test" : 2} , { "test" : 4}]}]} 
+0

ない、 'Query.criteria()は'のみ(フィールド名)文字列を受け取り、両方のアレイが 'Criteria'オブジェクトのリストであるとして。代わりの方法はありません。また、単一または句を作成するために配列を渡したので、私はMorphiaコードをチェックアウトし、このシナリオのテストケースを書く必要があります。 – chrisbunney

+0

より良い答えで更新されました。あなたのために働くことを願っています。 –

+0

更新していただきありがとうございます、それは面白いですね。私の実際のクエリは、私の意図を説明するために与えた単純な例よりも複雑ですが、原則は健全であると仮定しました。おそらく問題はクエリコードのどこかにあります。これは単なる症状です... – chrisbunney