У меня есть две коллекции MongoDB, которые имеют общий _id. Используя оболочку mongo, я хочу найти все документы в одной коллекции, которые не имеют соответствующего _id в другой коллекции.
Пример:
> db.Test.insert({ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "foo" : 1 })
> db.Test.insert({ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "foo" : 2 })
> db.Test.insert({ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 })
> db.Test.insert({ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 })
> db.Test.find()
{ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "foo" : 1 }
{ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "foo" : 2 }
{ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 }
{ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 }
> db.Test2.insert({ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "bar" : 1 });
> db.Test2.insert({ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "bar" : 2 });
> db.Test2.find()
{ "_id" : ObjectId("4f08a75f306b428fb9d8bb2e"), "bar" : 1 }
{ "_id" : ObjectId("4f08a766306b428fb9d8bb2f"), "bar" : 2 }
Теперь мне нужен запрос или запросы, которые возвращают два документа в тесте, где _id не соответствуют любому документу в Test2:
{ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 }
{ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 }
Я пробовал различные комбинации $not, $ne, $или, $in, но просто не могу получить правильную комбинацию и синтаксис. Кроме того, я не против, если db.Test2.find({}, {"_id": 1})
выполняется сначала, сохраняется в некоторой переменной, которая затем используется во втором запросе (хотя я не могу заставить это работать).
Обновить: ответ Zachary, указывающий на $nin, ответил на ключевую часть вопроса. Например, это работает:
> db.Test.find({"_id": {"$nin": [ObjectId("4f08a75f306b428fb9d8bb2e"), ObjectId("4f08a766306b428fb9d8bb2f")]}})
{ "_id" : ObjectId("4f08a767306b428fb9d8bb30"), "foo" : 3 }
{ "_id" : ObjectId("4f08a769306b428fb9d8bb31"), "foo" : 4 }
Но (и признавая, что это не масштабируемо, но все равно пытается это сделать, потому что это не проблема в этой ситуации), я все равно не могу объединить два запроса вместе в оболочке. Это самое близкое, что я могу получить, что явно меньше идеала:
vals = db.Test2.find({}, {"_id": 1}).toArray()
db.Test.find({"_id": {"$nin": [ObjectId(vals[0]._id), ObjectId(vals[1]._id)]}})
Есть ли способ вернуть только значения в команде find, так что vals можно использовать напрямую, поскольку массив вводится в $nin?