Morphia中的复杂AND-OR查询

chr*_*ney 9 java mongodb morphia

我一直在尝试组合Query接口的and()和or()方法来创建一组条件,其中有2个条件列表,并且必须满足每个条件中的至少一个条件.

我阅读了这个讨论,并一直在尝试使用Query.and()来组合我的两个$或子句.

基本上,我想说:

Criteria[] arrayA;
Criteria[] arrayB;

// Programatically populate both arrays

Query q = dao.createQuery().and(
    q.or(arrayA),
    q.or(arrayB)
);
Run Code Online (Sandbox Code Playgroud)

我正在使用标准数组,因为我必须遍历几个不同的输入以生成我需要的特定条件,这种方法适用于我只使用单个$或者,但我不能让Morphia生成查询我希望当我尝试在$中包含$或$时,如上所述.我发现没有$和查询以及第二个$或者已经覆盖了第一个$,就像我只是简单地调用或()两次一样.

例如,我希望生成一个查询,如下所示:

{
    "$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,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我只是得到这样的查询:

{
    "$or": {
        "0": //Some other criteria,
        "1": //Some other criteria,
        "2": //Some other criteria,
    }
}
Run Code Online (Sandbox Code Playgroud)

我看不到很多文档,但看看测试用例,这似乎是解决这个问题的正确方法.任何人都可以帮助解释为什么这不符合我的预期吗?

(这个问题被交叉发布到Morphia邮件列表,因为我不确定哪个地方会得到最好的回复)

编辑0:

更新:重新审视这个,我已经检查了Morphia测试代码,并且每件事情都运行良好,我一直无法在测试代码中重现我的问题.

因此,我创建了一个新项目来尝试获取我想要的查询的工作示例.但是,即使使用准系统测试项目,我也遇到了同样的问题.

该项目已经成熟,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>
Run Code Online (Sandbox Code Playgroud)

我有一个TestEntity类:

import java.util.Map;

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

@Entity
public class TestEntity {
    Map<String, Integer> map;
}
Run Code Online (Sandbox Code Playgroud)

最后我的测试类:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

对我来说,上面的代码不会产生正确的$和查询,但我不明白为什么

Eve*_*man 9

只是猜测(没时间测试),但它应该是:

Query q = dao.createQuery().and(
  q.or(q.criteria(arrayA)),
  q.or(q.criteria(arrayB))
);
Run Code Online (Sandbox Code Playgroud)

更新你是对的,Query.criteria不对 - 它是在简单测试中使用的,所以我认为你错过了一些东西.这似乎对我有用(将其分为两个陈述):

Query q = dao.createQuery();
q.and(
  q.or(arrayA),
  q.or(arrayB)
);
Run Code Online (Sandbox Code Playgroud)

更新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());
Run Code Online (Sandbox Code Playgroud)

得到:

{ "$and" : [ { "$or" : [ { "test" : 1} , { "test" : 3}]} , { "$or" : [ { "test" : 2} , { "test" : 4}]}]}
Run Code Online (Sandbox Code Playgroud)


chr*_*ney 6

尽管Morphia 0.99包括该Query.and(Criteria ...)方法,但它不会生成正确的查询.

第338期解决了对查询中显式$和子句的支持,目标是Morphia 0.99.1,目前只能通过Maven作为SNAPSHOT版本使用.

但是,使用0.99.1-SNAPSHOT解决了我们的问题.

  • - 如果能给出最终的,有效的例子,我会很高兴. (2认同)