如何撰写查询,例如(A || B || C)&& MongoDB Java Driver 3.2

时间:2016-10-12 14:41:17

标签: java mongodb

不幸的是,我找不到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>());

2 个答案:

答案 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/3896066https://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运算符而不是$或   操作