不幸的是,我找不到Mongo 3.2 java驱动程序的示例,例如“(A或B或C)和(D或E或F或G)”
括号内的参数数量可变 - 最多100 。
有趣的是,我找到了“(A&& B)||(X&& Y)”的例子,但它对我没有帮助。
How to execute queries with both AND and OR clauses in MongoDB with Java
我的代码产生错误:
MongoQueryException:查询失败,错误代码为2,错误消息为“$或/ $和/ $,条目也不必是完整对象”
List<Document> docs = new ArrayList<>();
for (Integer ln: input.getLastnames()) {
docs.add(new Document("lastname",ln));
}
Document queryLN = new Document(
"$or", Arrays.asList(docs)
);
docs.clear();
for (Integer fn: input.getFirstnames()) {
docs.add(new Document("firstname",fn));
}
Document queryFN = new Document(
"$or", Arrays.asList(docs)
);
Document query = new Document(
"$and", Arrays.asList(queryFN,queryLN));
List<Document> result = collectionMain.find(query).into(new ArrayList<Document>());
答案 0 :(得分:3)
你应该使用&#34; in&#34;当你有一个很长的未知OR条件列表时,在这种情况下查询。
示例代码:
try {
MongoClient mongo = new MongoClient();
DB db = mongo.getDB("so");
DBCollection coll = db.getCollection("employees");
List<Integer> ageList = new ArrayList<>();
ageList.add(30);
ageList.add(35);
List<String> nameList = new ArrayList<>();
nameList.add("Anna");
BasicDBObject query = new BasicDBObject("$and", Arrays.asList(
new BasicDBObject("age", new BasicDBObject("$in", ageList)),
new BasicDBObject("name", new BasicDBObject("$in", nameList)))
);
DBCursor cursor = coll.find(query);
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
}catch (Exception ex){
ex.printStackTrace();
}
要试验上面的代码,您可以在MongoDB中添加以下条目:
db.employees.insert({"name":"Adma","dept":"Admin","languages":["german","french","english","hindi"],"age":30, "totalExp":10});
db.employees.insert({"name":"Anna","dept":"Admin","languages":["english","hindi"],"age":35, "totalExp":11});
db.employees.insert({"name":"Bob","dept":"Facilities","languages":["english","hindi"],"age":36, "totalExp":14});
db.employees.insert({"name":"Cathy","dept":"Facilities","languages":["hindi"],"age":31, "totalExp":4});
db.employees.insert({"name":"Mike","dept":"HR","languages":["english", "hindi", "spanish"],"age":26, "totalExp":3});
db.employees.insert({"name":"Jenny","dept":"HR","languages":["english", "hindi", "spanish"],"age":25, "totalExp":3});
以上代码生成此查询:
db.employees.find({"$and":[{"age":{"$in":[30, 35]}},{"name":{"$in":["Anna"]}}]});
输出是:
{ "_id" : { "$oid" : "57ff3e5e3dedf0228d4862ad"} , "name" : "Anna" , "dept" : "Admin" , "languages" : [ "english" , "hindi"] , "age" : 35.0 , "totalExp" : 11.0}
关于此主题的好文章:https://www.mkyong.com/mongodb/java-mongodb-query-document/
请阅读以下内容:https://stackoverflow.com/a/8219679/3896066和https://stackoverflow.com/a/14738878/3896066
答案 1 :(得分:1)
让我们先了解您的代码。我们将通过用简单语句替换for循环并添加一些打印语句来简化它。
List<Document> docs = new ArrayList<>();
docs.add(new Document("lastname","Walker"));
docs.add(new Document("lastname","Harris"));
Document queryLN = new Document("$or", Arrays.asList(docs));
docs.clear();
System.out.println(queryLN.toJson());//{ "$or" : [[]] }
docs.add(new Document("firstname", "Pat"));
docs.add(new Document("firstname", "Matt"));
Document queryFN = new Document("$or", Arrays.asList(docs));
System.out.println(queryLN.toJson());//{ "$or" : [[{ "firstname" : "Pat" }, { "firstname" : "Matt" }]] }
System.out.println(queryFN.toJson());//{ "$or" : [[{ "firstname" : "Pat" }, { "firstname" : "Matt" }]] }
Document query = new Document("$and", Arrays.asList(queryFN, queryLN));
System.out.println(query.toJson());//{ "$and" : [{ "$or" : [[{ "firstname" : "Pat" }, { "firstname" : "Matt" }]] }, { "$or" : [[{ "firstname" : "Pat" }, { "firstname" : "Matt" }]] }] }
List<Document> result = collectionMain.find(query).into(new ArrayList<Document>());
<强>观察:强>
docs
已经是一个列表。在Arrays.asList
上使用docs
创建一个列表列表,$and, $or, $nor
无法接受。这些运算符接受list of Documents
。这解释了错误消息。
Arrays.asList
不会创建数组的副本或它接收的列表。它只是在它上面创建一个包装器。此外,new document()
不会复制它使用“$或”接收的列表,只是引用原始列表。因此,调用docs.clear()
会重置$or
queryLN
中的内容。
此外,上述概念解释了为什么第2和第3个印刷语句提供相同的输出。
让我们现在开始使用代码。
List<Document> docsLN = new ArrayList<Document>();
List<Document> docsFN = new ArrayList<Document>();
for (Integer ln: input.getLastnames()) {
docsLN.add(new Document("lastname",ln));
}
Document queryLN = new Document("$or", docsLN);
for (Integer fn: input.getFirstnames()) {
docsFN.add(new Document("firstname",fn));
}
Document queryFN = new Document("$or", docsFN);
System.out.println(queryLN.toJson());
System.out.println(queryFN.toJson());
Document query = new Document("$and", Arrays.asList(queryFN, queryLN));
System.out.println(query.toJson());
List<Document> result = collectionMain.find(query).into(new ArrayList<Document>());
另外,请考虑将$or
替换为$in
。
来自docs:
当使用$或者使用它时,是对...的等式检查 相同字段的值,使用$ in运算符而不是$或 操作