10

Query インターフェースの and() メソッドと or() メソッドを組み合わせて、2 つの基準リストがあり、それぞれから少なくとも 1 つが満たされなければならない一連の条件を作成しようとしました。

このディスカッションを読んで、Query.and() を使用して 2 つの $or 句を結合しようとしました。

本質的に、私は言おうとしています:

Criteria[] arrayA;
Criteria[] arrayB;

// Programatically populate both arrays

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

必要な特定の基準を生成するためにいくつかの異なる入力をループする必要があるため、基準の配列を使用しています。このアプローチは、単一の $or を使用している場合に機能しますが、Morphia にクエリを生成させることはできません。上記で説明したように、 $and に $or 句の両方を含めようとすると期待できます。$and クエリがなく、単に or() を 2 回呼び出したかのように、2 番目の $or が最初の $or を上書きしたことがわかりました。

たとえば、次のようにクエリが生成されることを期待しています。

{
    "$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,
    }
}

ドキュメントはあまり見当たりませんが、テストケースを見ると、これが正しい方法のようです。なぜこれが期待どおりに機能しないのか、誰かが光を当てるのを助けることができますか?

(この質問はMorphia メーリング リストにクロスポストされました。どの場所が最適な回答を得るかわからないためです)

編集 0 :

更新: これを再確認して、Morphia テスト コードをチェックアウトしましたが、すべて正常に動作しました。テスト コードで問題を再現できませんでした。

したがって、新しいプロジェクトを作成して、必要なクエリの実際の例を取得しようとしました。ただし、ベアボーン テスト プロジェクトでも同じ問題が発生しました。

プロジェクトはMavenizedで、POMは次のとおりです。

<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>

私は TestEntity クラスを持っています:

import java.util.Map;

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

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

そして最後に私のテストクラス:

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);
    }
}

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

4

2 に答える 2

9

推測するだけです(テストする時間がありません)が、次のようになります。

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

更新そうです、そうでQuery.criteriaはありませんでした。それは簡単なテストで使用されたものだったので、何かを見落としていると思いました。これは私にとってはうまくいくようです(2つのステートメントに分けます):

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}]}]}
于 2012-04-23T16:28:24.243 に答える
6

メソッドを含む Morphia 0.99 にもかかわらずQuery.and(Criteria ...)、正しいクエリが生成されません。

クエリでの明示的な$and句のサポートに対処するIssue 338は、現在 Maven を介した SNAPSHOT バージョンとしてのみ利用可能な Morphia 0.99.1 を対象としています。

ただし、0.99.1-SNAPSHOT を使用すると問題が解決しました。

于 2012-05-01T11:46:05.963 に答える