Ответ 1
db.tests.find({deleted: {$ne: true}})
Где $ne
означает "не равно". (Документация по операторам mongodb)
Я уверен, что в запросах 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}
Что мне не хватает?
db.tests.find({deleted: {$ne: true}})
Где $ne
означает "не равно". (Документация по операторам mongodb)
Для полноты, другой способ сделать это - $in
:
db.test.find({deleted: {$in: [null, false]}})
Включение null
в массив вытягивает документы, где отсутствует поле deleted
. Этот запрос может использовать индекс в {deleted: 1}
в текущей версии 2.6.6 MongoDB.
У 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)