You can use below aggregation:
db.UserDetails.aggregate(
{
$lookup: {
from: "UserProducts",
localField: "UID",
foreignField: "UID",
as: "userProduct"
}
},
{ $unwind: "$userProduct" },
{
"$project": { "_id" : 0, "userProduct.UPID" : 1 }
},
{
$group: {
_id: null,
userProductUPIDs: { $addToSet: "$userProduct.UPID" }
}
},
{
$lookup: {
from: "Groups",
pipeline: [
{ $unwind: "$members.regularStudent" },
{ $project: { _id: 0, value: "$members.regularStudent" } }
],
as: "UPID"
}
},
{
$addFields: {
UPID: {
$map: {
input: "$UPID",
as: "x",
in: "$$x.value"
}
}
}
},
{
$project: {
result: {
$setDifference: [ "$userProductUPIDs", "$UPID" ]
}
}
}
)
Basically the aim is to get single document with two arrays to perform $setDifference. You already have the right part (just need to add $group) and you need $lookup with custom pipeline to get all the data from Groups
into one collection. Outputs:
{ "_id" : null, "result" : [ "100" ] }
EDIT: to run $lookup
with custom pipeline you need MongoDB 3.6 or newer. Alternatively you have to run two aggregations and then compare both results in your application logic:
var queryResult = db.UserDetails.aggregate(
{
$lookup: {
from: "UserProducts",
localField: "UID",
foreignField: "UID",
as: "userProduct"
}
},
{ $unwind: "$userProduct" },
{
"$project": { "_id" : 0, "userProduct.UPID" : 1 }
},
{
$group: {
_id: null,
userProductUPIDs: { $addToSet: "$userProduct.UPID" }
}
}
) // returns [ "100", "200" ]
let userProductUPIDs = queryResult.toArray()[0].userProductUPIDs;
db.Groups.aggregate([
{
$unwind: "$members.regularStudent"
},
{
$group: {
_id: null,
UPIDs: { $addToSet: "$members.regularStudent" }
}
},
{
$project: {
members: {
$setDifference: [ userProductUPIDs , "$UPIDs" ]
},
_id : 0
}
}
])