92

我确定我在 MongoDB 查询中遗漏了一些非常基本的东西,似乎无法得到这个简单的条件。

考虑这个集合

> db.tests.find()
{ "_id" : ObjectId("..."), "name" : "Test1" , "deleted" : true}
{ "_id" : ObjectId("..."), "name" : "Test2" , "deleted" : false}
{ "_id" : ObjectId("..."), "name" : "Test3" }

我只想查询所有“未删除”的项目

我知道如何找到将“已删除”标志设置为 true 的项目:

> db.tests.find({deleted:true})
{ "_id" : ObjectId("..."), "name" : "Test1" , "deleted" : true}

但是我如何找到所有不是的项目"deleted"(例如否定上述查询,或者换句话说,任何没有"deleted"字段或有值的项目false

我通过猜测尝试的(请不要笑...)

> db.tests.find({$not : {deleted: true}})

(不返回任何结果)

> db.tests.find({$not : {$eq:{deleted:true}}})

错误:{“$err”:“无效运算符:$eq”,“代码”:10068 }

> db.tests.find({deleted:{$not: true}})

错误:{“$err”:“$not 的无效使用”,“code”:13041}

> db.tests.find({deleted:{$not: {$eq:true}}})

错误:{“$err”:“$not 的无效使用”,“代码”:13034 }

我错过了什么?

4

5 回答 5

169
db.tests.find({deleted: {$ne: true}})

where$ne代表“不相等”。(关于 mongodb 操作符的文档

于 2013-09-16T21:18:58.863 回答
36

为了完整起见,另一种方法是使用$in

db.test.find({deleted: {$in: [null, false]}})

包含null在数组中会拉入deleted缺少该字段的文档。此查询可以使用{deleted: 1}当前 2.6.6 MongoDB 版本中的索引。

于 2015-01-14T21:56:11.527 回答
7

JohnnyHK 给出了最好的答案。选择$in器是最短和最干净的 IMO。

这将完全测试“错误”或“不存在”。并且可以被索引。

db.tests.find({$or:[{deleted:false},{deleted:{$exists:false}}]})

使用索引的示例。

((function(){
    print("creating collection 'testx' and inserting 50 trues, 50 falses, 50 non-existents");
    db.testx.drop();
    db.testx.ensureIndex({deleted:1});
    for (var i=0;i<50;i++){
        db.testx.insert({i:i,deleted:false});
    };
    for (var i=0;i<50;i++){
        db.testx.insert({i:i,deleted:true});
    };
    for (var i=0;i<50;i++){
        db.testx.insert({i:i});
    };
    var res0 = db.testx.find().explain();
    var res1 = db.testx.find({deleted:false}).explain();
    var res2 = db.testx.find({deleted:true}).explain();
    var res3 = db.testx.find({deleted:{$exists:false}}).explain();
    var res4 = db.testx.find({$or:[{deleted:false},{deleted:{$exists:false}}]}).explain();
    var res5 = db.testx.find({$or:[{deleted:true},{deleted:{$exists:false}}]}).explain();
    var res6 = db.testx.find({deleted:{$in:[false,null]}}).explain();
    print("res0: all objects                      ("+res0["n"]+" found, "+res0["nscannedObjects"]+" scanned)");
    print("res1: deleted is false                 ("+res1["n"]+" found, "+res1["nscannedObjects"]+" scanned)");
    print("res2: deleted is true                  ("+res2["n"]+" found, "+res2["nscannedObjects"]+" scanned)");
    print("res3: deleted is non-existent          ("+res3["n"]+" found, "+res3["nscannedObjects"]+" scanned)");
    print("res4: deleted is false or non-existent ("+res4["n"]+" found, "+res4["nscannedObjects"]+" scanned)");
    print("res5: deleted is true or non-existent  ("+res5["n"]+" found, "+res5["nscannedObjects"]+" scanned)");
    print("res6: deleted is in [false,null]       ("+res5["n"]+" found, "+res5["nscannedObjects"]+" scanned)");
})())

这应该打印

creating collection 'testx' and inserting 50 trues, 50 falses, 50 non-existents
res0: all objects                      (150 found, 150 scanned)
res1: deleted is false                 (50 found, 50 scanned)
res2: deleted is true                  (50 found, 50 scanned)
res3: deleted is non-existent          (50 found, 50 scanned)
res4: deleted is false or non-existent (100 found, 100 scanned)
res5: deleted is true or non-existent  (100 found, 100 scanned)
res6: deleted is in [false,null]       (100 found, 100 scanned)
于 2014-09-07T12:45:36.333 回答
1

对于有人在聚合管道中需要它而不是 的情况find,这对我有用

db.getCollection('tests').aggregate([ 
  // ...previous operations...
  { $addFields: { "deleted_conclusion": { $cond: {
        if:{ $ne: [ "$deleted", false ]}, then: { $cond: [ "$deleted", ":TRUE", ":FALSY"]}, else: ":FALSE"
  }}}}
])

添加额外字段后,您可以继续进行管道阶段并获取您错过的信息

于 2018-04-11T14:23:52.303 回答
0

如果您正在寻找 mongoid 语法(我在 rails 应用程序中使用它),这就是我为公司用户想出的:

2.3.1 :042 > accepted_consent = org.users.active.where(:accepted_terms_and_conditions => true).count
 => 553 
2.3.1 :043 > not_accepted_yet = org.users.active.where(:accepted_terms_and_conditions.ne => true).count
 => 6331 
2.3.1 :044 > 6331+553
 => 6884 
2.3.1 :045 > org.users.active.count
 => 6884 
于 2018-05-27T00:14:37.637 回答