查询布尔字段为“不为真”(例如,假或不存在)

时间:2013-09-16 21:18:21

标签: mongodb

我确定我在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”,“代码”:13041}

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

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

我错过了什么?

5 个答案:

答案 0 :(得分:114)

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

$ne代表“不相等”。 (Documentation on mongodb operators

答案 1 :(得分:25)

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

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

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

答案 2 :(得分:6)

JohnnyHK有最好的答案。 $in选择器是最短,最干净的IMO。

这将完全测试" false"或者"不存在"。并且可以编入索引。

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)

答案 3 :(得分:0)

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

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

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

答案 4 :(得分: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 
相关问题