diff --git a/lib/schema.js b/lib/schema.js index d857b7ba636..270463d3b5d 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -746,8 +746,10 @@ Schema.prototype.path = function(path, obj) { // Skip arrays of document arrays if (_schemaType.$isMongooseDocumentArray) { + _schemaType.$embeddedSchemaType._arrayPath = arrayPath; _schemaType = _schemaType.$embeddedSchemaType.clone(); } else { + _schemaType.caster._arrayPath = arrayPath; _schemaType = _schemaType.caster.clone(); } diff --git a/lib/schema/array.js b/lib/schema/array.js index 3986bddc559..bc828a178ab 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -300,7 +300,7 @@ SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) { * @api private */ -SchemaArray.prototype.cast = function(value, doc, init) { +SchemaArray.prototype.cast = function(value, doc, init, prev, options) { // lazy load MongooseArray || (MongooseArray = require('../types').Array); @@ -355,7 +355,13 @@ SchemaArray.prototype.cast = function(value, doc, init) { if (this.caster.instance === 'Number' && value[i] === void 0) { throw new MongooseError('Mongoose number arrays disallow storing undefined'); } - value[i] = this.caster.cast(value[i], doc, init); + const opts = {}; + if (options != null && options.arrayPath != null) { + opts.arrayPath = options.arrayPath + '.' + i; + } else if (this.caster._arrayPath != null) { + opts.arrayPath = this.caster._arrayPath.slice(0, -2) + '.' + i; + } + value[i] = this.caster.cast(value[i], doc, init, void 0, opts); } } catch (e) { // rethrow diff --git a/lib/schema/documentarray.js b/lib/schema/documentarray.js index 3ec0e3cc27d..57e2fa441b0 100644 --- a/lib/schema/documentarray.js +++ b/lib/schema/documentarray.js @@ -364,6 +364,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) { let selected; let subdoc; const _opts = { transform: false, virtuals: false }; + options = options || {}; if (!Array.isArray(value)) { if (!init && !DocumentArrayPath.options.castNonArrays) { @@ -374,11 +375,11 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) { if (!!doc && init) { doc.markModified(this.path); } - return this.cast([value], doc, init, prev); + return this.cast([value], doc, init, prev, options); } if (!(value && value.isMongooseDocumentArray) && - (!options || !options.skipDocumentArrayCast)) { + !options.skipDocumentArrayCast) { value = new MongooseDocumentArray(value, this.path, doc); } else if (value && value.isMongooseDocumentArray) { // We need to create a new array, otherwise change tracking will @@ -386,6 +387,10 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) { value = new MongooseDocumentArray(value, this.path, doc); } + if (options.arrayPath != null) { + value[arrayPathSymbol] = options.arrayPath; + } + const len = value.length; for (let i = 0; i < len; ++i) {