Reputation: 15
How can I update just one piece in a document with Mongoose, when the json elements are nested?
I would like to update a document and just set the "darkMode" from false to true, without GETing and PUTing the whole "settins" part. Is this possible with Mongoose?
"settings": {
"darkMode": false,
"tipOfTheDay": true,
"paperFormat": "DINA4",
},
If I PUT this, I will lose everything in the "settings" part of the document:
"settings": {
"darkMode": true,
},
My NodeJS backend looks like this. I am using the findByIdAndUpdate at the moment. Maybe there is a better method?
exports.updateProfile = async (req, res, next) => {
const profile = await Profile.findByIdAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true
});
if (!profile) {
return res.status(400).json({success: false});
}
res.status(200).json({success: true, data: profile});
}
Upvotes: 1
Views: 640
Reputation: 1624
In order to update a field in an embbeded document you must use the a $set
operator (since your document is an object we are dealing with an object within an object)
From the mongodb documentation :
Update Specific Fields in Embedded Documents Use dot notation to update values in embedded documents.
So for you, if we assume that req.body here is { darkMode: true }
it would be
const profile = await Profile.findByIdAndUpdate(
req.params.id,
{ $set: { 'settings.darkMode': req.body.darkMode } },
{
new: true,
runValidators: true
});
But it all depends on how you send the data from the client, if you send an object containing only modified fields then you must specifically $set them to keep the other value intact like above. To automate this you could also build your query using a fancy loop :
let query = { $set: {} }
Object.keys(req.body).forEach(requestBodyKey => {
let requestBodyFieldValue = req.body[requestBodyKey];
query.$set[`settings.${requestBodyKey}`] = requestBodyFieldValue;
})
Or you can first query your document to get the current_settings, then using javascript you would merge the two objects (e.g. {...myCurrentSettings, ...myNewerSettings }
see spread operator or Object.assign()) and then update it to ensure that you keep the previous, untouched, field values.
Upvotes: 1