mongoose 5.5.3 → 5.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/History.md CHANGED
@@ -1,3 +1,15 @@
1
+ 5.5.4 / 2019-04-25
2
+ ==================
3
+ * fix(document): avoid calling custom getters when saving #7719
4
+ * fix(timestamps): handle child schema timestamps correctly when reusing child schemas #7712
5
+ * fix(query): pass correct callback for _legacyFindAndModify #7736 [Fonger](https://github.com/Fonger)
6
+ * fix(model+query): allow setting `replacement` parameter for `findOneAndReplace()` #7654
7
+ * fix(map): make `delete()` unset the key in the database #7746 [Fonger](https://github.com/Fonger)
8
+ * fix(array): use symbol for `_schema` property to avoid confusing deep equality checks #7700
9
+ * fix(document): prevent `depopulate()` from removing fields with empty array #7741 #7740 [Fonger](https://github.com/Fonger)
10
+ * fix: make `MongooseArray#includes` support ObjectIds #7732 #6354 [Fonger](https://github.com/Fonger)
11
+ * fix(document): report correct validation error index when pushing onto doc array #7744 [Fonger](https://github.com/Fonger)
12
+
1
13
  5.5.3 / 2019-04-22
2
14
  ==================
3
15
  * fix: add findAndModify deprecation warning that references the useFindAndModify option #7644
package/lib/document.js CHANGED
@@ -2547,22 +2547,22 @@ Document.prototype.$__getAllSubdocs = function() {
2547
2547
  Embedded = Embedded || require('./types/embedded');
2548
2548
 
2549
2549
  function docReducer(doc, seed, path) {
2550
- const val = path ? doc[path] : doc;
2550
+ let val = doc;
2551
+ if (path) {
2552
+ val = doc instanceof Document ? doc._doc[path] : doc[path];
2553
+ }
2551
2554
  if (val instanceof Embedded) {
2552
2555
  seed.push(val);
2553
- }
2554
- else if (val instanceof Map) {
2556
+ } else if (val instanceof Map) {
2555
2557
  seed = Array.from(val.keys()).reduce(function(seed, path) {
2556
2558
  return docReducer(val.get(path), seed, null);
2557
2559
  }, seed);
2558
- }
2559
- else if (val && val.$isSingleNested) {
2560
+ } else if (val && val.$isSingleNested) {
2560
2561
  seed = Object.keys(val._doc).reduce(function(seed, path) {
2561
2562
  return docReducer(val._doc, seed, path);
2562
2563
  }, seed);
2563
2564
  seed.push(val);
2564
- }
2565
- else if (val && val.isMongooseDocumentArray) {
2565
+ } else if (val && val.isMongooseDocumentArray) {
2566
2566
  val.forEach(function _docReduce(doc) {
2567
2567
  if (!doc || !doc._doc) {
2568
2568
  return;
@@ -3339,7 +3339,7 @@ Document.prototype.depopulate = function(path) {
3339
3339
  if (virtualKeys.indexOf(path[i]) !== -1) {
3340
3340
  delete this.$$populatedVirtuals[path[i]];
3341
3341
  delete this._doc[path[i]];
3342
- } else {
3342
+ } else if (populatedIds) {
3343
3343
  this.$set(path[i], populatedIds);
3344
3344
  }
3345
3345
  }
@@ -9,19 +9,19 @@ const hasParentPointers = Symbol('Mongoose.helpers.setParentPointers');
9
9
  * This is a slow path function, should only run when model is compiled
10
10
  */
11
11
 
12
- module.exports = function setParentPointers(schema) {
12
+ module.exports = function setParentPointers(schema, parentSchemaType) {
13
13
  if (schema[hasParentPointers]) {
14
14
  return;
15
15
  }
16
16
  schema[hasParentPointers] = true;
17
17
  for (const path of Object.keys(schema.paths)) {
18
18
  const schemaType = schema.paths[path];
19
- if (schemaType.schema != null) {
20
- Object.defineProperty(schemaType.schema, '$schemaType', {
19
+ if (parentSchemaType != null) {
20
+ Object.defineProperty(schemaType, '$parentSchemaType', {
21
21
  configurable: true,
22
22
  writable: false,
23
23
  enumerable: false,
24
- value: schemaType
24
+ value: parentSchemaType
25
25
  });
26
26
  }
27
27
  Object.defineProperty(schemaType, '$parentSchema', {
@@ -35,7 +35,7 @@ module.exports = function setParentPointers(schema) {
35
35
  for (const path of Object.keys(schema.paths)) {
36
36
  const type = schema.paths[path];
37
37
  if (type.$isSingleNested || type.$isMongooseDocumentArray) {
38
- setParentPointers(type.schema, false);
38
+ setParentPointers(type.schema, type);
39
39
  }
40
40
  }
41
41
  };
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  exports.arrayParentSymbol = Symbol('mongoose#Array#_parent');
4
- exports.documentArrayParent = Symbol.for('mongoose:documentArrayParent');
5
- exports.getSymbol = Symbol.for('mongoose#Document#get');
6
- exports.modelSymbol = Symbol.for('mongoose#Model');
7
- exports.objectIdSymbol = Symbol.for('mongoose#ObjectId');
8
- exports.schemaTypeSymbol = Symbol.for('mongoose#schemaType');
9
- exports.validatorErrorSymbol = Symbol.for('mongoose:validatorError');
4
+ exports.arraySchemaSymbol = Symbol('mongoose#Array#_schema');
5
+ exports.documentArrayParent = Symbol('mongoose:documentArrayParent');
6
+ exports.getSymbol = Symbol('mongoose#Document#get');
7
+ exports.modelSymbol = Symbol('mongoose#Model');
8
+ exports.objectIdSymbol = Symbol('mongoose#ObjectId');
9
+ exports.schemaTypeSymbol = Symbol('mongoose#schemaType');
10
+ exports.validatorErrorSymbol = Symbol('mongoose:validatorError');
@@ -63,18 +63,24 @@ function applyTimestampsToChildren(now, update, schema) {
63
63
  if (!path) {
64
64
  continue;
65
65
  }
66
+
67
+ let parentSchemaType = null;
68
+ const pieces = keyToSearch.split('.');
69
+ for (let i = pieces.length - 1; i > 0; --i) {
70
+ const s = schema.path(pieces.slice(0, i).join('.'));
71
+ if (s != null &&
72
+ (s.$isMongooseDocumentArray || s.$isSingleNested)) {
73
+ parentSchemaType = s;
74
+ break;
75
+ }
76
+ }
77
+
66
78
  if (Array.isArray(update.$set[key]) && path.$isMongooseDocumentArray) {
67
79
  applyTimestampsToDocumentArray(update.$set[key], path, now);
68
80
  } else if (update.$set[key] && path.$isSingleNested) {
69
81
  applyTimestampsToSingleNested(update.$set[key], path, now);
70
- } else if (path.$parentSchema !== schema && path.$parentSchema != null) {
71
- const parentPath = path.$parentSchema.$schemaType;
72
-
73
- if (parentPath == null) {
74
- continue;
75
- }
76
-
77
- timestamps = parentPath.schema.options.timestamps;
82
+ } else if (parentSchemaType != null) {
83
+ timestamps = parentSchemaType.schema.options.timestamps;
78
84
  createdAt = handleTimestampOption(timestamps, 'createdAt');
79
85
  updatedAt = handleTimestampOption(timestamps, 'updatedAt');
80
86
 
@@ -82,23 +88,23 @@ function applyTimestampsToChildren(now, update, schema) {
82
88
  continue;
83
89
  }
84
90
 
85
- if (parentPath.$isSingleNested) {
91
+ if (parentSchemaType.$isSingleNested) {
86
92
  // Single nested is easy
87
- update.$set[parentPath.path + '.' + updatedAt] = now;
93
+ update.$set[parentSchemaType.path + '.' + updatedAt] = now;
88
94
  continue;
89
95
  }
90
96
 
91
- let childPath = key.substr(parentPath.path.length + 1);
92
- const firstDot = childPath.indexOf('.');
97
+ let childPath = key.substr(parentSchemaType.path.length + 1);
93
98
 
94
- // Shouldn't happen, but if it does ignore this path
95
- if (firstDot === -1) {
99
+ if (/^\d+$/.test(childPath)) {
100
+ update.$set[parentSchemaType.path + '.' + childPath][updatedAt] = now;
96
101
  continue;
97
102
  }
98
103
 
99
- childPath = childPath.substr(0, firstDot);
104
+ const firstDot = childPath.indexOf('.');
105
+ childPath = firstDot !== -1 ? childPath.substr(0, firstDot) : childPath;
100
106
 
101
- update.$set[parentPath.path + '.' + childPath + '.' + updatedAt] = now;
107
+ update.$set[parentSchemaType.path + '.' + childPath + '.' + updatedAt] = now;
102
108
  } else if (path.schema != null && path.schema != schema && update.$set[key]) {
103
109
  timestamps = path.schema.options.timestamps;
104
110
  createdAt = handleTimestampOption(timestamps, 'createdAt');
package/lib/model.js CHANGED
@@ -2603,7 +2603,8 @@ Model.findByIdAndDelete = function(id, options, callback) {
2603
2603
  *
2604
2604
  * - defaults. Use the `setDefaultsOnInsert` option to override.
2605
2605
  *
2606
- * @param {Object} conditions
2606
+ * @param {Object} filter Replace the first document that matches this filter
2607
+ * @param {Object} [replacement] Replace with this document
2607
2608
  * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2608
2609
  * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](http://mongoosejs.com/docs/api.html#query_Query-lean).
2609
2610
  * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
@@ -2613,18 +2614,24 @@ Model.findByIdAndDelete = function(id, options, callback) {
2613
2614
  * @api public
2614
2615
  */
2615
2616
 
2616
- Model.findOneAndReplace = function(conditions, options, callback) {
2617
- if (arguments.length === 1 && typeof conditions === 'function') {
2618
- const msg = 'Model.findOneAndDelete(): First argument must not be a function.\n\n'
2619
- + ' ' + this.modelName + '.findOneAndDelete(conditions, callback)\n'
2620
- + ' ' + this.modelName + '.findOneAndDelete(conditions)\n'
2621
- + ' ' + this.modelName + '.findOneAndDelete()\n';
2617
+ Model.findOneAndReplace = function(filter, replacement, options, callback) {
2618
+ if (arguments.length === 1 && typeof filter === 'function') {
2619
+ const msg = 'Model.findOneAndReplace(): First argument must not be a function.\n\n'
2620
+ + ' ' + this.modelName + '.findOneAndReplace(conditions, callback)\n'
2621
+ + ' ' + this.modelName + '.findOneAndReplace(conditions)\n'
2622
+ + ' ' + this.modelName + '.findOneAndReplace()\n';
2622
2623
  throw new TypeError(msg);
2623
2624
  }
2624
2625
 
2625
- if (typeof options === 'function') {
2626
+ if (arguments.length === 3 && typeof options === 'function') {
2626
2627
  callback = options;
2627
- options = undefined;
2628
+ options = replacement;
2629
+ replacement = void 0;
2630
+ }
2631
+ if (arguments.length === 2 && typeof replacement === 'function') {
2632
+ callback = replacement;
2633
+ replacement = void 0;
2634
+ options = void 0;
2628
2635
  }
2629
2636
  if (callback) {
2630
2637
  callback = this.$wrapCallback(callback);
@@ -2639,7 +2646,7 @@ Model.findOneAndReplace = function(conditions, options, callback) {
2639
2646
  const mq = new this.Query({}, {}, this, this.collection);
2640
2647
  mq.select(fields);
2641
2648
 
2642
- return mq.findOneAndReplace(conditions, options, callback);
2649
+ return mq.findOneAndReplace(filter, replacement, options, callback);
2643
2650
  };
2644
2651
 
2645
2652
  /**
@@ -4486,8 +4493,8 @@ function convertTo_id(val) {
4486
4493
  val[i] = val[i]._id;
4487
4494
  }
4488
4495
  }
4489
- if (val.isMongooseArray && val._schema) {
4490
- return val._schema.cast(val, val.$parent());
4496
+ if (val.isMongooseArray && val.$schema()) {
4497
+ return val.$schema().cast(val, val.$parent());
4491
4498
  }
4492
4499
 
4493
4500
  return [].concat(val);
package/lib/query.js CHANGED
@@ -3118,16 +3118,17 @@ Query.prototype._findOneAndDelete = wrapThunk(function(callback) {
3118
3118
  *
3119
3119
  * ####Examples
3120
3120
  *
3121
- * A.where().findOneAndReplace(conditions, options, callback) // executes
3122
- * A.where().findOneAndReplace(conditions, options) // return Query
3123
- * A.where().findOneAndReplace(conditions, callback) // executes
3124
- * A.where().findOneAndReplace(conditions) // returns Query
3125
- * A.where().findOneAndReplace(callback) // executes
3126
- * A.where().findOneAndReplace() // returns Query
3121
+ * A.where().findOneAndReplace(filter, replacement, options, callback); // executes
3122
+ * A.where().findOneAndReplace(filter, replacement, options); // return Query
3123
+ * A.where().findOneAndReplace(filter, replacement, callback); // executes
3124
+ * A.where().findOneAndReplace(filter); // returns Query
3125
+ * A.where().findOneAndReplace(callback); // executes
3126
+ * A.where().findOneAndReplace(); // returns Query
3127
3127
  *
3128
3128
  * @method findOneAndReplace
3129
3129
  * @memberOf Query
3130
- * @param {Object} [conditions]
3130
+ * @param {Object} [filter]
3131
+ * @param {Object} [replacement]
3131
3132
  * @param {Object} [options]
3132
3133
  * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
3133
3134
  * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
@@ -3138,28 +3139,39 @@ Query.prototype._findOneAndDelete = wrapThunk(function(callback) {
3138
3139
  * @api public
3139
3140
  */
3140
3141
 
3141
- Query.prototype.findOneAndReplace = function(conditions, options, callback) {
3142
+ Query.prototype.findOneAndReplace = function(filter, replacement, options, callback) {
3142
3143
  this.op = 'findOneAndReplace';
3143
3144
  this._validate();
3144
3145
 
3145
3146
  switch (arguments.length) {
3146
- case 2:
3147
+ case 3:
3147
3148
  if (typeof options === 'function') {
3148
3149
  callback = options;
3149
- options = {};
3150
+ options = void 0;
3151
+ }
3152
+ break;
3153
+ case 2:
3154
+ if (typeof replacement === 'function') {
3155
+ callback = replacement;
3156
+ replacement = void 0;
3150
3157
  }
3151
3158
  break;
3152
3159
  case 1:
3153
- if (typeof conditions === 'function') {
3154
- callback = conditions;
3155
- conditions = undefined;
3156
- options = undefined;
3160
+ if (typeof filter === 'function') {
3161
+ callback = filter;
3162
+ filter = void 0;
3163
+ replacement = void 0;
3164
+ options = void 0;
3157
3165
  }
3158
3166
  break;
3159
3167
  }
3160
3168
 
3161
- if (mquery.canMerge(conditions)) {
3162
- this.merge(conditions);
3169
+ if (mquery.canMerge(filter)) {
3170
+ this.merge(filter);
3171
+ }
3172
+
3173
+ if (replacement != null) {
3174
+ this._mergeUpdate(replacement);
3163
3175
  }
3164
3176
 
3165
3177
  options && this.setOptions(options);
@@ -3419,7 +3431,7 @@ Query.prototype._findAndModify = function(type, callback) {
3419
3431
  if (error) {
3420
3432
  return callback(error);
3421
3433
  }
3422
- _legacyFindAndModify.call(_this, castedQuery, castedDoc, opts, callback);
3434
+ _legacyFindAndModify.call(_this, castedQuery, castedDoc, opts, cb);
3423
3435
  };
3424
3436
 
3425
3437
  try {
@@ -3428,7 +3440,7 @@ Query.prototype._findAndModify = function(type, callback) {
3428
3440
  callback(error);
3429
3441
  }
3430
3442
  } else {
3431
- _legacyFindAndModify.call(_this, castedQuery, castedDoc, opts, callback);
3443
+ _legacyFindAndModify.call(_this, castedQuery, castedDoc, opts, cb);
3432
3444
  }
3433
3445
 
3434
3446
  return this;
@@ -362,7 +362,9 @@ DocumentArray.prototype.cast = function(value, doc, init, prev, options) {
362
362
 
363
363
  if (value[i] instanceof Subdocument) {
364
364
  // Might not have the correct index yet, so ensure it does.
365
- value[i].$setIndex(i);
365
+ if (value[i].__index == null) {
366
+ value[i].$setIndex(i);
367
+ }
366
368
  } else if (value[i] != null) {
367
369
  if (init) {
368
370
  if (doc) {
@@ -14,6 +14,7 @@ const utils = require('../utils');
14
14
  const util = require('util');
15
15
 
16
16
  const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
17
+ const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
17
18
  const isMongooseObject = utils.isMongooseObject;
18
19
 
19
20
  /**
@@ -44,7 +45,7 @@ function MongooseArray(values, path, doc) {
44
45
  arr.isMongooseArray = true;
45
46
  arr.validators = [];
46
47
  arr._atomics = {};
47
- arr._schema = void 0;
48
+ arr[arraySchemaSymbol] = void 0;
48
49
  if (util.inspect.custom) {
49
50
  arr[util.inspect.custom] = arr.inspect;
50
51
  }
@@ -55,7 +56,7 @@ function MongooseArray(values, path, doc) {
55
56
  // to make more proof against unusual node environments
56
57
  if (doc && doc instanceof Document) {
57
58
  arr[arrayParentSymbol] = doc;
58
- arr._schema = doc.schema.path(path);
59
+ arr[arraySchemaSymbol] = doc.schema.path(path);
59
60
  }
60
61
 
61
62
  return arr;
@@ -86,6 +87,14 @@ MongooseArray.mixin = {
86
87
  return this[arrayParentSymbol];
87
88
  },
88
89
 
90
+ /*!
91
+ * ignore
92
+ */
93
+
94
+ $schema: function() {
95
+ return this[arraySchemaSymbol];
96
+ },
97
+
89
98
  /**
90
99
  * Casts a member based on this arrays schema.
91
100
  *
@@ -122,10 +131,10 @@ MongooseArray.mixin = {
122
131
  if (!isDisc) {
123
132
  value = new Model(value);
124
133
  }
125
- return this._schema.caster.applySetters(value, this[arrayParentSymbol], true);
134
+ return this[arraySchemaSymbol].caster.applySetters(value, this[arrayParentSymbol], true);
126
135
  }
127
136
 
128
- return this._schema.caster.applySetters(value, this[arrayParentSymbol], false);
137
+ return this[arraySchemaSymbol].caster.applySetters(value, this[arrayParentSymbol], false);
129
138
  },
130
139
 
131
140
  /**
@@ -321,7 +330,7 @@ MongooseArray.mixin = {
321
330
  push: function() {
322
331
  _checkManualPopulation(this, arguments);
323
332
  let values = [].map.call(arguments, this._mapCast, this);
324
- values = this._schema.applySetters(values, this[arrayParentSymbol], undefined,
333
+ values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol], undefined,
325
334
  undefined, { skipDocumentArrayCast: true });
326
335
  const ret = [].push.apply(this, values);
327
336
 
@@ -612,7 +621,7 @@ MongooseArray.mixin = {
612
621
  _checkManualPopulation(this, arguments);
613
622
 
614
623
  let values = [].map.call(arguments, this._cast, this);
615
- values = this._schema.applySetters(values, this[arrayParentSymbol]);
624
+ values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol]);
616
625
  [].unshift.apply(this, values);
617
626
  this._registerAtomic('$set', this);
618
627
  this._markModified();
@@ -658,7 +667,7 @@ MongooseArray.mixin = {
658
667
  _checkManualPopulation(this, arguments);
659
668
 
660
669
  let values = [].map.call(arguments, this._mapCast, this);
661
- values = this._schema.applySetters(values, this[arrayParentSymbol]);
670
+ values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol]);
662
671
  const added = [];
663
672
  let type = '';
664
673
  if (values[0] instanceof EmbeddedDocument) {
@@ -786,6 +795,20 @@ MongooseArray.mixin = {
786
795
  }
787
796
  }
788
797
  return -1;
798
+ },
799
+
800
+ /**
801
+ * Return whether or not the `obj` is included in the array.
802
+ *
803
+ * @param {Object} obj the item to check
804
+ * @return {Boolean}
805
+ * @api public
806
+ * @method includes
807
+ * @memberOf MongooseArray
808
+ */
809
+
810
+ includes: function includes(obj) {
811
+ return this.indexOf(obj) !== -1;
789
812
  }
790
813
  };
791
814
 
@@ -830,7 +853,9 @@ function _isAllSubdocs(docs, ref) {
830
853
  */
831
854
 
832
855
  function _checkManualPopulation(arr, docs) {
833
- const ref = get(arr, '_schema.caster.options.ref', null);
856
+ const ref = arr == null ?
857
+ null :
858
+ get(arr[arraySchemaSymbol], 'caster.options.ref', null);
834
859
  if (arr.length === 0 &&
835
860
  docs.length > 0) {
836
861
  if (_isAllSubdocs(docs, ref)) {
@@ -8,13 +8,13 @@ const Document = require('../document');
8
8
  const MongooseArray = require('./array');
9
9
  const ObjectId = require('./objectid');
10
10
  const castObjectId = require('../cast/objectid');
11
- const get = require('../helpers/get');
12
11
  const getDiscriminatorByValue = require('../queryhelpers').getDiscriminatorByValue;
13
12
  const internalToObjectOptions = require('../options').internalToObjectOptions;
14
13
  const util = require('util');
15
14
  const utils = require('../utils');
16
15
 
17
16
  const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
17
+ const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
18
18
  const documentArrayParent = require('../helpers/symbols').documentArrayParent;
19
19
 
20
20
  /*!
@@ -50,7 +50,7 @@ function MongooseDocumentArray(values, path, doc) {
50
50
  isMongooseDocumentArray: true,
51
51
  validators: [],
52
52
  _atomics: {},
53
- _schema: void 0,
53
+ [arraySchemaSymbol]: void 0,
54
54
  _handlers: void 0
55
55
  };
56
56
 
@@ -95,21 +95,23 @@ function MongooseDocumentArray(values, path, doc) {
95
95
  // to make more proof against unusual node environments
96
96
  if (doc && doc instanceof Document) {
97
97
  arr[arrayParentSymbol] = doc;
98
- arr._schema = doc.schema.path(path);
98
+ arr[arraySchemaSymbol] = doc.schema.path(path);
99
99
 
100
100
  // `schema.path()` doesn't drill into nested arrays properly yet, see
101
101
  // gh-6398, gh-6602. This is a workaround because nested arrays are
102
102
  // always plain non-document arrays, so once you get to a document array
103
103
  // nesting is done. Matryoshka code.
104
- while (get(arr, '_schema.$isMongooseArray') &&
105
- !get(arr, '_schema.$isMongooseDocumentArray')) {
106
- arr._schema = arr._schema.casterConstructor;
104
+ while (arr != null &&
105
+ arr[arraySchemaSymbol] != null &&
106
+ arr[arraySchemaSymbol].$isMongooseArray &&
107
+ !arr[arraySchemaSymbol].$isMongooseDocumentArray) {
108
+ arr[arraySchemaSymbol] = arr[arraySchemaSymbol].casterConstructor;
107
109
  }
108
110
 
109
111
  // Tricky but this may be a document array embedded in a normal array,
110
112
  // in which case `path` would point to the embedded array. See #6405, #6398
111
- if (arr._schema && !arr._schema.$isMongooseDocumentArray) {
112
- arr._schema = arr._schema.casterConstructor;
113
+ if (arr[arraySchemaSymbol] && !arr[arraySchemaSymbol].$isMongooseDocumentArray) {
114
+ arr[arraySchemaSymbol] = arr[arraySchemaSymbol].casterConstructor;
113
115
  }
114
116
 
115
117
  arr._handlers = {
@@ -145,7 +147,7 @@ MongooseDocumentArray.mixin = {
145
147
  */
146
148
 
147
149
  _cast: function(value, index) {
148
- let Constructor = this._schema.casterConstructor;
150
+ let Constructor = this[arraySchemaSymbol].casterConstructor;
149
151
  const isInstance = Constructor.$isMongooseDocumentArray ?
150
152
  value && value.isMongooseDocumentArray :
151
153
  value instanceof Constructor;
@@ -294,7 +296,7 @@ MongooseDocumentArray.mixin = {
294
296
  */
295
297
 
296
298
  create: function(obj) {
297
- let Constructor = this._schema.casterConstructor;
299
+ let Constructor = this[arraySchemaSymbol].casterConstructor;
298
300
  if (obj &&
299
301
  Constructor.discriminators &&
300
302
  Constructor.schema &&
package/lib/types/map.js CHANGED
@@ -83,6 +83,11 @@ class MongooseMap extends Map {
83
83
  }
84
84
  }
85
85
 
86
+ delete(key) {
87
+ this.set(key, undefined);
88
+ super.delete(key);
89
+ }
90
+
86
91
  toBSON() {
87
92
  return new Map(this);
88
93
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "5.5.3",
4
+ "version": "5.5.4",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -25,7 +25,7 @@
25
25
  "mongodb": "3.2.2",
26
26
  "mongodb-core": "3.2.2",
27
27
  "mongoose-legacy-pluralize": "1.0.2",
28
- "mpath": "0.5.1",
28
+ "mpath": "0.5.2",
29
29
  "mquery": "3.2.0",
30
30
  "ms": "2.1.1",
31
31
  "regexp-clone": "0.0.1",