Database

db={conversations2:[{"_id":{"$oid":"65c0f64030054c4b8f0481a0"},"otherUserId":{"$numberLong":"45"},"userId":{"$numberLong":"32"},"unreadMessageCount":29},{"_id":{"$oid":"65c0f64030054c4b8f0481a1"},"otherUserId":{"$numberLong":"46"},"userId":{"$numberLong":"32"},"unreadMessageCount":10},{"_id":{"$oid":"65c0f64030054c4b8f0481a2"},"otherUserId":{"$numberLong":"47"},"userId":{"$numberLong":"32"},"unreadMessageCount":0}],user_blocked:[{"_id":{"$oid":"660285eb2be53086024608e6"},"id":{"$numberLong":"45"}},{"_id":{"$oid":"660285eb2be53086024608e7"},"id":{"$numberLong":"555"}}]}

Query

db.conversations2.aggregate([{$match:{userId:32,unreadMessageCount:{$gt:0}}},{/** collect all the unique `otherUserId` for this userId*/$group:{_id:null,otherUserIds:{$addToSet:"$otherUserId"}}},{/** correlated but will only run once since* the previous stage has only one document*/$lookup:{from:"user_blocked",let:{lookupOtherUserIds:"$otherUserIds"},pipeline:[{$match:{$expr:{$ne:[{$indexOfArray:["$$lookupOtherUserIds","$id"]},-1]}}},{$group:{_id:null,ids:{$addToSet:"$id"}}}],as:"blockedUsers"}},{/** otherIDs which remain after removing blockedIDs*/$project:{validOtherIds:{$setDifference:["$otherUserIds",{$first:"$blockedUsers.ids"}]}}},{/** do a self-lookup on `conversations2`*/$lookup:{from:"conversations2",let:{lookupValidOtherIds:"$validOtherIds"},/** repeat part of the first stage of this pipeline, yuck!*/pipeline:[{$match:{userId:32,/** unread > 0 check is not needed since* lookupValidOtherIds already has only > 0's*/$expr:{$ne:[{$indexOfArray:["$$lookupValidOtherIds","$otherUserId"]},-1]}}}],as:"validConvos"}},/** the `group` below can be directly done in the self-lookup stage* but I find this cleaner*/{$unwind:"$validConvos"},{$group:{_id:null,unreadMessageCount:{$sum:"$validConvos.unreadMessageCount"}}}])

Result