我一直在尝试组合Query接口的and()和or()方法来创建一组条件,其中有2个条件列表,并且每个条件必须满足至少一个条件。
我读了this discussion并且一直在尝试使用Query.and()来合并我的两个$或子句。
基本上,我想说:
Criteria[] arrayA;
Criteria[] arrayB;
// Programatically populate both arrays
Query q = dao.createQuery().and(
q.or(arrayA),
q.or(arrayB)
);
我正在使用标准数组,因为我必须遍历几个不同的输入以生成我需要的特定条件,这种方法适用于我只使用单个$或者,但我不能让Morphia来生成我期望的查询,当我尝试在$中包含$或子句时,如上所述。我发现没有$和查询,第二个$或者已经覆盖了第一个,就好像我只是简单地调用了或()两次。
E.g我希望像这样生成一个查询:
{
"$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测试代码并且每件事情都运行正常,我无法在测试代码中重现我的问题。
因此,我创建了一个新项目来尝试获取我想要的查询的工作示例。但是,即使使用准系统测试项目,我也遇到了同样的问题。
项目已经成熟,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);
}
}
对我来说,上面的代码没有产生正确的$和查询,但我看不出为什么
答案 0 :(得分:9)
猜测(没时间测试),但应该是:
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}]}]}
答案 1 :(得分:6)
尽管Morphia 0.99包括Query.and(Criteria ...)
方法,但它不会生成正确的查询。
Issue 338解决了对查询中显式 $和子句的支持,目标是Morphia 0.99.1,目前只能通过Maven作为SNAPSHOT版本使用。
然而,使用0.99.1-SNAPSHOT解决了我们的问题。