I have the following query that should update the privacyStatus
of a user to some value, and also remove all notifications
(an array of ObjectIds
) which have a type
property equal to the value: follow_request
.
User.aggregate([
{
$match: { _id: new mongoose.Types.ObjectId(req.user._id) },
},
{
$lookup: {
from: "Notification",
localField: "notifications",
foreignField: "_id",
as: "notifications",
},
},
{
$set: {
privacyStatus: value,
notifications: {
$filter: {
input: "$notifications",
cond: {
$ne: ["$$this.type", "follow_request"],
},
},
},
},
},
{
$merge: {
into: "users",
},
},
]).then((result) => {
res.send("Done")
})
The privacyStatus
is successfully updated in the database, therefore I know the $match
stage is working correctly, however the notifications
array doesn't update at all even if there are notifications that match the filter.
My User model:
{
privacyStatus: {type: Boolean},
notifications: [type: mongoose.Schema.Types.ObjectId,ref: "Notification",]
}
Notification Model:
{
type: {type: String, default: "follow_request"}
}
Why aren't my notifications that have a type of follow_request
being removed from the users notification
array? Thanks
Sample documents: user document:
{
_id: ObjectId('66324110da2f0f7175ca1949'),
username: "sam",
notifications: [
ObjectId('663c1c0bd0sa68fae7cf6ad2')
]
}
Notification document:
{
_id: ObjectId('663c1c0bd0sa68fae7cf6ad2'),
type: "follow_request"
}
To get your aggregate
to merge the results back intot he users
collection you need to do two things:
$lookup
from Notification
to notifications
.User.notifications
field is an array of ObjectId
s. When your $filter
returns it's results, you won't be able $merge
them back into your User.notifications
array because they will be full Notification
documents. That can be fixed with a $map
stage to step over each filtered Notification
document and only return their _id
. Then that will match your schema.The finished aggregation might look like this:
User.aggregate([
{
$match: {
_id: new mongoose.Types.ObjectId(req.user._id)
}
},
{
$lookup: {
from: "notifications", //< change to this
localField: "notifications",
foreignField: "_id",
as: "notifications"
}
},
{
$set: {
privacyStatus: value,
notifications: {
$map: {
input: {
$filter: {
input: "$notifications",
cond: {
$ne: [
"$$this.type",
"follow_request"
]
}
}
},
as: "n",
in: "$$n._id"
}
}
}
},
{
$merge: {
into: "users"
}
}
]).then((result) => {
res.send("Done")
})
See HERE for a working example.