Reputation: 2376
I would like to use mongoose in this case. Let's say we have a Schema like this:
const userSchema = new Schema({
name: {
first: { type: String, required: true },
last: { type: String, required: true },
},
email: { type: String, required: true, unique: true, lowercase: true },
});
Let's say we already have document with first and last name. I need to update only first name and email with the following args object:
const updateUser = {
name: {
first: Eddy,
},
email: '[email protected]'
};
If it will be used with mongoose update methods in most cases it would also change last name to null
. That's because JavaScript doesn't support deep object merge and so on. So what's the best way to gain possibility to merge objects properly?
I've found the way to do it below but it doesn't seem to be the best solution:
User.findById(args.id, (error, user) => {
if (error) throw err;
user.name.first = args.name.first ? args.name.first : user.name.first;
user.name.last = args.name.last ? args.name.last : user.name.last;
user.email = args.email ? args.email : user.email;
user.save((err, updatedUser) => {
if (err) throw err;
return updatedUser;
});
});
I and Eslint don't like this with reassigning and unmaintainable code. Have somebody better idea? I'm not sure that I need to use lodash and other libs only for this capability.
Upvotes: 3
Views: 1290
Reputation: 2376
Here is what I've done with this issue.
Thanks to Neil Lunn with this idea.
We're need to map all object keys to dot.notation and pass to the $set.
Here is the gist with this function. If we need two level nesting we can add another condition and mapping.
Anyway I hope that Mongoose API will resolve us to make deep merge with nested objects, but for now Neil's solution is the best in my opinion.
Upvotes: 1