'Mongoose: multi: true for a projection update doesn't work?
Having a document with the following structure:
{
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Story' },
notifications: [{
story: {
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Story' },
video_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Video' }
},
video: {
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Video' },
video_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Video' }
},
type: { type: String },
read: { type: Number, default: 0 }, // 0 - Unread, 1 - read
ts: { type: Date, default: Date.now }
}]
}
I'm trying to mark as read all notifications which read element equals to 0, but for any reason, my code only modifies the first notification:
mongoose.model('User').update({ _id: user_id, 'notifications.read': 0 }, { $set: { 'notifications.$.read': 1 }}, { multi: true });
Am I using correctly the multi: true?
UPDATE
I'd say what I'm trying to do, doesn't have any sense by using the placeholder since as the doc says:
$. Acts as a placeholder to update the first element that matches the query condition in an update.
Solution 1:[1]
When you use { _id: user_id, 'notifications.read': 0 } this to update the document, it will only find one document, because you are querying by the _id.
You should use {'notifications.read': 0 } instead.
Solution 2:[2]
You must use the $ placeholder, but to modify multiple embedded documents in one query it's necessary to use the arrayFilters as well, as specified here. Also, you don't have to use multi: true.
In your case it would look like this:
mongoose.model('User').updateOne(
{ _id: user_id },
{ $set: { 'notifications.$[element].read': 1 } },
{ arrayFilters: [{ 'element.read': 0 }] }
)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dhanush Gopinath |
| Solution 2 | Ernani |
