Database

db={"videos":[{"_id":"1","name":"1's Video","status":"complete","privacy":"public"},{"_id":"2","name":"2's Video","status":"complete","privacy":"public"},{"_id":"3","name":"3's Video","status":"complete","privacy":"public"},{"_id":"4","name":"4's Video","status":"complete","privacy":"private"},{"_id":"5","name":"5's Video","status":"flagged","privacy":"public"}],"analytics":[{"_id":"1","user":"1","event":"video_impression","data":{"video":"1"}},{"_id":"2","user":"2","event":"video_impression","data":{"video":"2"}},{"_id":"3","user":"2","event":"video_impression","data":{"video":"3"}},{"_id":"4","user":"2","event":"liked_video","data":{"video":"2"}}]}

Query

db.analytics.aggregate([{/** select only the video_impression events*/$match:{event:"video_impression"}},{/** uniquify your users but you should probably* run this from the 'users' collection*/$group:{_id:"$user",impressioned_vids:{"$addToSet":"$data.video"},/** remove this if you want the user as _id*/user:{"$first":"$user"}}},{$project:{_id:0}},{/** correlated subquery which executes per record*/$lookup:{from:"videos",let:{seen_vid_ids:"$impressioned_vids"},pipeline:[{$match:{status:"complete",privacy:"public",/** I wanted to do:* _id: { $nin: "$$seen_vid_ids" } // syntax error* or even* _id: { $nin: ["$$seen_vid_ids"] } // doesn't work** but instead had to do this*/$expr:{$eq:[{"$setIntersection":[["$_id"],"$$seen_vid_ids"]},[]]}}}],as:"unseen_vids"}},{/** these are the public-complete videos which that user has not seen*/$set:{unimpressed:"$unseen_vids._id"}},{/** get rid of the other fields, uncomment to debug*/$project:{user:1,unimpressed:1}}])

Result