Подтвердить что ты не робот

Запрос для логического поля как "не верно" (например, ложный или не существующий)

Я уверен, что в запросах MongoDB отсутствует что-то очень основное, похоже, не получается получить это простое условие.

Рассмотрим эту коллекцию

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

Я просто хотел бы запросить все элементы, которые не удалены

Я знаю, как найти элемент с флагом "deleted", установленным в 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}}})

error: { "$ err" : "invalid operator: $eq", "code" : 10068}

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

error: { "$ err" : "неверное использование $not", "code" : 13041}

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

error: { "$ err" : "неверное использование $not", "code" : 13034}

Что мне не хватает?

4b9b3361

Ответ 2

Для полноты, другой способ сделать это - $in:

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

Включение null в массив вытягивает документы, где отсутствует поле deleted. Этот запрос может использовать индекс в {deleted: 1} в текущей версии 2.6.6 MongoDB.

Ответ 3

У 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)