Do you want to request a feature or report a bug?
Bug
What is the current behavior?
Using lodash's set method (https://lodash.com/docs/4.17.15#set) to set a nested property is resulting in all the other properties of the nested object to be set to undefined.
If the current behavior is a bug, please provide the steps to reproduce.
const mongoose = require("mongoose");
const _ = require("lodash");
const Schema = mongoose.Schema;
const schema = new Schema({
nested: {
prop1: { type: Number, default: 50 },
prop2: {
type: String, enum: ['val1', 'val2'], default: 'val1', required: true,
},
prop3: {
prop4: { type: Number, default: 0 },
},
},
});
const Model = mongoose.model("model", schema);
mongoose.connect("mongodb://localhost:27017/test").then(async () => {
let doc = await Model.create({});
console.log('nested.prop2 after creation', doc.nested.prop2); // nested.prop2 is correctly set to the default value `val1`
doc = await Model.findOne(doc._id).exec();
console.log('nested.prop2 after fetch', doc.nested.prop2); // nested.prop2 is correctly `val1`
_.set(doc, 'nested.prop1', 45);
console.log('nested.prop2 after _.set', doc.nested.prop2); // // nested.prop2 is now undefined, as well as all other properties in the `nested` object apart from `nested.prop1`
await doc.save(); // this will fail because nested.prop2 is required
}).catch(err => console.log(err));
What is the expected behavior?
The properties are set correctly. Note that for some strange reason removing prop3 from the schema the bug doesn't appear. It looks like it only happens when there are at least 3 nested properties.
What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
It started happening in 5.9.28, 5.9.27 works fine. On node 12
You're right, I can reproduce it too in mongoose 5.9.28. I'm curious how it happens, will try to take a look...
Yeah the conditions to replicate it are pretty strange, I'm not sure why it's happening but looking at the changes in 5.9.28 it should be due to these lines https://github.com/Automattic/mongoose/compare/5.9.27...5.9.28#diff-e51f9847487dfe7cf44f998bf9b8b8e8R141
That link doesn't work for me...
https://github.com/Automattic/mongoose/compare/5.9.27...5.9.28 the changes for lib/helpers/document/compile.js at the set method
Very likely you're right. For reference that commit mentions #9293
I've cooked it down to remove lodash from the equation. Essentially this is what lodash is doing as part of its algorithm, it seems. Just assigning the "nested" field to itself makes it disappear...
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const util = require("util");
const schema = new Schema({
nested: {
prop1: { type: Number, default: 50 },
prop2: {
type: String, enum: ['val1', 'val2'], default: 'val1', required: true,
},
prop3: {
prop4: { type: Number, default: 0 },
},
},
});
const Model = mongoose.model("model", schema);
mongoose.connect("mongodb://localhost:27017/test").then(async () => {
let doc = await Model.create({});
console.log('nested.prop2 after creation', doc.nested.prop2); // nested.prop2 is correctly set to the default value `val1`
doc = await Model.findOne(doc._id).exec();
console.log('nested.prop2 after fetch', doc.nested.prop2); // nested.prop2 is correctly `val1`
// NEW CODE HERE, LOOK!
console.log(util.inspect(doc, true)); // Has all properties as before
doc.nested = doc.nested;
console.log(util.inspect(doc, true)); // Now, missing nested completely
// The rest is unimportant...
await doc.save(); // this will fail because nested.prop2 is required
}).catch(err => console.log(err));
This, however, works:
//...
console.log(util.inspect(doc, true)); // Has all properties as before
let ne = doc.nested;
doc.nested = {prop1: ne.prop1, prop2: ne.prop2, prop3: ne.prop3}
console.log(util.inspect(doc, true)); // This way, it still works and has all the properties
//...
but this does not:
//...
console.log(util.inspect(doc, true)); // Has all properties as before
let ne = doc.nested;
doc.nested = Object.assign(ne, {});
console.log(util.inspect(doc, true)); // nested is missing
//...
That tells me the other hidden $-properies mongoose adds are tripping it up, and the logic for them is flawed with the version 28 addition, just as you said.
We got the same problem here, we had to revert back to a previous Mongoose version.
Same issue here...
Thanks for reporting this issue. Bug is fixed and fix will be in 5.9.29 :+1: