diff --git a/lib/document.js b/lib/document.js index 917910ac5d4..8893c91f101 100644 --- a/lib/document.js +++ b/lib/document.js @@ -878,6 +878,13 @@ Document.prototype.$__set = function(pathToMark, path, constructing, parts, sche if (val && val.isMongooseArray) { val._registerAtomic('$set', val); + // Update embedded document parent references (gh-5189) + if (val.isMongooseDocumentArray) { + val.forEach(function(item) { + item && item.__parentArray && (item.__parentArray = val); + }); + } + // Small hack for gh-1638: if we're overwriting the entire array, ignore // paths that were modified before the array overwrite this.$__.activePaths.forEach(function(modifiedPath) { diff --git a/test/document.modified.test.js b/test/document.modified.test.js index 2eecd53ca80..1f1ff26e24d 100644 --- a/test/document.modified.test.js +++ b/test/document.modified.test.js @@ -465,6 +465,28 @@ describe('document modified', function() { done(); }); + + it('updates embedded doc parents upon direct assignment (gh-5189)', function(done) { + var db = start(); + var familySchema = new Schema({ + children: [{name: {type: String, required: true}}] + }); + var Family = db.model('Family', familySchema); + Family.create({ + children: [ + {name: 'John'}, + {name: 'Mary'} + ] + }, function(err, family) { + family.set({children: family.children.slice(1)}); + family.children.forEach(function(child) { + child.set({name: 'Maryanne'}); + }); + + assert.equal(family.validateSync(), undefined); + done(); + }); + }); }); it('should support setting mixed paths by string (gh-1418)', function(done) {