diff --git a/lib/document.js b/lib/document.js index 413b0de35b7..0183ce47e51 100644 --- a/lib/document.js +++ b/lib/document.js @@ -856,7 +856,7 @@ Document.prototype.$set = function $set(path, val, type, options) { this.schema.paths[pathName].options && this.schema.paths[pathName].options.ref)) { this.$__.$setCalled.add(prefix + key); - this.$set(path[key], prefix + key, constructing); + this.$set(path[key], prefix + key, constructing, options); } else if (strict) { // Don't overwrite defaults with undefined keys (gh-3981) if (constructing && path[key] === void 0 && @@ -876,10 +876,10 @@ Document.prototype.$set = function $set(path, val, type, options) { path[key] instanceof Document) { p = p.toObject({ virtuals: false, transform: false }); } - this.$set(prefix + key, p, constructing); + this.$set(prefix + key, p, constructing, options); } else if (pathtype === 'nested' && path[key] instanceof Document) { this.$set(prefix + key, - path[key].toObject({transform: false}), constructing); + path[key].toObject({transform: false}), constructing, options); } else if (strict === 'throw') { if (pathtype === 'nested') { throw new ObjectExpectedError(key, path[key]); @@ -888,7 +888,7 @@ Document.prototype.$set = function $set(path, val, type, options) { } } } else if (path[key] !== void 0) { - this.$set(prefix + key, path[key], constructing); + this.$set(prefix + key, path[key], constructing, options); } } @@ -1034,6 +1034,18 @@ Document.prototype.$set = function $set(path, val, type, options) { return this; } + if (schema.$isSingleNested && val != null && merge) { + if (val instanceof Document) { + val = val.toObject({ virtuals: false, transform: false }); + } + const keys = Object.keys(val); + for (const key of keys) { + this.$set(path + '.' + key, val[key], constructing, options); + } + + return this; + } + let shouldSet = true; try { // If the user is trying to set a ref path to a document with @@ -1097,11 +1109,11 @@ Document.prototype.$set = function $set(path, val, type, options) { didPopulate = true; } - // If this path is underneath a single nested schema, we'll call the setter - // later in `$__set()` because we don't take `_doc` when we iterate through - // a single nested doc. That's to make sure we get the correct context. - // Otherwise we would double-call the setter, see gh-7196. if (this.schema.singleNestedPaths[path] == null) { + // If this path is underneath a single nested schema, we'll call the setter + // later in `$__set()` because we don't take `_doc` when we iterate through + // a single nested doc. That's to make sure we get the correct context. + // Otherwise we would double-call the setter, see gh-7196. val = schema.applySetters(val, this, false, priorVal); }