Reputation: 2803
I'm trying to find all users except for a few, like this:
// get special user IDs
var special = db.special.find({}, { _id: 1 }).toArray();
// get all users except for the special ones
var users = db.users.find({_id: {$nin: special}});
This doesn't work because the array that I'm passing to $nin
is not and array of ObjectId
but an array of { _id: ObjectId() }
Variable special
looks like this after the first query:
[ { _id: ObjectId(###) }, { _id: ObjectId(###) } ]
But $nin
in the second query needs this:
[ ObjectId(###), ObjectId(###) ]
How can I get just the ObjectId()
in an array from the first query so that I can use them in the second query?
Or, is there a better way of achieving what I'm trying to do?
Upvotes: 1
Views: 1332
Reputation: 103375
Use the cursor.map()
method returned by the find()
function to transform the list of { _id: ObjectId(###) }
documents to an array of ObjectId
's as in the following
var special = db.special.find({}, { _id: 1 }).map(function(doc){
return doc._id;
});
Another approach you can consider is using the $lookup
operator in the aggregation framework to do a "left outer join" on the special
collection and filtering the documents on the new "joined" array field. The filter should match on documents whose array field is empty.
The following example demonstrates this:
db.users.aggregate([
{
"$lookup": {
"from": "special",
"localField": "_id",
"foreignField": "_id",
"as": "specialUsers" // <-- this will produce an arry of "joined" docs
}
},
{ "$match": { "specialUsers.0": { "$exists": false } } } // <-- match on empty array
])
Upvotes: 3