Reputation: 305
I'm working on an API, in my frontend, I send a PATCH request to a route that can update weight, height or gender. The structure of my schema model is this:
/** @format */
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema(
{
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
email: { type: String, required: true, unique: true },
userNumber: { type: Number, required: true },
description: { type: String },
verified: { type: Boolean, default: false },
isAdmin: { type: Boolean, default: false },
isSubscriber: { type: Boolean, default: false },
isDisabled: { type: Boolean, default: false },
characteristics: {
height: { type: Number, default: 0 },
weight: { type: Number, default: 0 },
gender: { type: String, default: 'other' },
},
acceptedTerms: { type: Number, required: true },
},
{ timestamps: true }
);
module.exports = mongoose.model('User', userSchema);
Now my controller actions are quite similar to find update those 3 values:
exports.changeSex = async (req, res, next) => {
// Requirements
const userId = req.params.userId;
const newGender = req.body.gender;
console.log('userId: ' + userId);
console.log('newGender: ' + req.body.gender);
try {
const user = await User.findOneAndUpdate(
{ _id: userId },
{ characteristics: { gender: newGender } }
);
console.log('User successfully updated.');
return res.status(200).json({ success: true, gender: newGender });
} catch (err) {
console.log('ERROR: ', err);
return res.status(400).json({ success: false, error: err });
}
};
The problem I'm facing is each time I execute one of these 3 actions, one replaces the others.
For example, changing gender, will output height: 0, and weight: 0, and if I update weight: 10, gender returns to gender: 'other'.
It seems findAndUpdateOne replaces everything using the default values of my schema, which would be a pity to rewrite the entire thing, I tried updateOne and I find the same result. I also tried this:
...
try {
const user = await User.findOneAndUpdate(
{ _id: userId },
{ $set: { characteristics: { gender: newGender } } }
);
...
and also:
try {
const user = await User.findOneAndUpdate(
{ _id: userId },
{ characteristics: {$set { gender: newGender } } }
);
And both examples also repeat the same pattern.
Upvotes: 0
Views: 471
Reputation: 198
This not a correct way to update object
value.
Try this:
exports.changeSex = async (req, res, next) => {
// Requirements
const userId = req.params.userId;
const newGender = req.body.gender;
console.log('userId: ' + userId);
console.log('newGender: ' + req.body.gender);
try {
const user = await User.findOneAndUpdate(
{ _id: userId },
{ $set: {
"characteristics.gender": newGender
}
},
{ returnDocument: 'after' }
);
console.log('User successfully updated.',user);
return res.status(200).json({ success: true, gender: newGender });
} catch (err) {
console.log('ERROR: ', err);
return res.status(400).json({ success: false, error: err });
}
};
{ returnDocument: 'after' }
is options of query. it's return document
after updating.If you have any doubt watch example : https://mongoplayground.net/p/w5WlqHxHghU
Upvotes: 2