From 167f68284098dcb67d733edc540cce596db44d4d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 4 Oct 2022 18:26:03 -0400 Subject: [PATCH 1/3] fix(document): set defaults on subdocuments underneath init-ed single nested subdocument Fix #12515 --- lib/schema/SubdocumentPath.js | 1 + test/document.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/schema/SubdocumentPath.js b/lib/schema/SubdocumentPath.js index e748d6a5026..46ea86673e0 100644 --- a/lib/schema/SubdocumentPath.js +++ b/lib/schema/SubdocumentPath.js @@ -174,6 +174,7 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) { subdoc = new Constructor(void 0, selected, doc, false, { defaults: false }); subdoc.$init(val); applyDefaults(subdoc, selected); + delete subdoc.$__.defaults; } else { if (Object.keys(val).length === 0) { return new Constructor({}, selected, doc, undefined, options); diff --git a/test/document.test.js b/test/document.test.js index ca2aca278d9..eebea364b3c 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -11865,6 +11865,33 @@ describe('document', function() { assert.strictEqual(called, 1); }); + it('applies defaults to pushed subdocs after initing document (gh-12515)', async function() { + const animalSchema = new Schema({ title: String }); + const animalsSchema = new Schema({ + species: [animalSchema], + totalAnimals: Number + }); + const Userschema = new Schema({ + animals: animalsSchema + }); + const UserModel = db.model('User', Userschema); + + const doc = new UserModel(); + doc.animals = { totalAnimals: 1 }; + doc.animals.species = [{ title: 'Lion' }]; + await doc.save(); + // once created we fetch it again + let user = await UserModel.findById(doc._id); + + // add new animal + user.animals.species.push({ title: 'Elephant' }); + await user.save(); + assert.ok(user.animals.species[1]._id); + user = await UserModel.collection.findOne({ _id: user._id }); + + assert.ok(user.animals.species[1]._id); + }); + it('If the field does not exist, $inc should create it and set is value to the specified one (gh-12435)', async function() { const schema = new mongoose.Schema({ name: String, From b0edca9f6d2ce957194f8229744140c08b325fb5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 5 Oct 2022 10:25:14 -0400 Subject: [PATCH 2/3] fix: quick fix so `defaults` is unset before init --- lib/schema/SubdocumentPath.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schema/SubdocumentPath.js b/lib/schema/SubdocumentPath.js index 46ea86673e0..1eb65207d85 100644 --- a/lib/schema/SubdocumentPath.js +++ b/lib/schema/SubdocumentPath.js @@ -172,9 +172,9 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) { options = Object.assign({}, options, { priorDoc: priorVal }); if (init) { subdoc = new Constructor(void 0, selected, doc, false, { defaults: false }); + delete subdoc.$__.defaults; subdoc.$init(val); applyDefaults(subdoc, selected); - delete subdoc.$__.defaults; } else { if (Object.keys(val).length === 0) { return new Constructor({}, selected, doc, undefined, options); From 630bd3738ea237934ac4f246fb97d868412b5d70 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 5 Oct 2022 11:04:04 -0400 Subject: [PATCH 3/3] test: cover a couple of extra cases for #12515 --- test/document.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/document.test.js b/test/document.test.js index eebea364b3c..2d38adc8629 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -11886,9 +11886,11 @@ describe('document', function() { // add new animal user.animals.species.push({ title: 'Elephant' }); await user.save(); + assert.ok(user.animals.species[0]._id); assert.ok(user.animals.species[1]._id); user = await UserModel.collection.findOne({ _id: user._id }); + assert.ok(user.animals.species[0]._id); assert.ok(user.animals.species[1]._id); });