mongoose 6.3.3 → 6.3.6

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.
Files changed (47) hide show
  1. package/.eslintrc.json +1 -1
  2. package/dist/browser.umd.js +1 -1
  3. package/lgtm.yml +12 -0
  4. package/lib/cast/objectid.js +3 -2
  5. package/lib/connection.js +3 -2
  6. package/lib/document.js +15 -8
  7. package/lib/error/index.js +2 -2
  8. package/lib/helpers/clone.js +9 -2
  9. package/lib/helpers/common.js +3 -4
  10. package/lib/helpers/discriminator/areDiscriminatorValuesEqual.js +2 -2
  11. package/lib/helpers/isBsonType.js +5 -3
  12. package/lib/helpers/path/setDottedPath.js +14 -1
  13. package/lib/helpers/topology/isAtlas.js +15 -2
  14. package/lib/helpers/update/applyTimestampsToChildren.js +4 -0
  15. package/lib/index.js +4 -3
  16. package/lib/model.js +38 -54
  17. package/lib/query.js +4 -1
  18. package/lib/queryhelpers.js +3 -2
  19. package/lib/schema/decimal128.js +4 -4
  20. package/lib/schema/map.js +8 -0
  21. package/lib/schema/objectid.js +4 -3
  22. package/lib/schema/string.js +2 -2
  23. package/lib/schema.js +41 -2
  24. package/lib/types/DocumentArray/methods/index.js +3 -3
  25. package/lib/types/array/methods/index.js +3 -3
  26. package/lib/types/map.js +4 -4
  27. package/lib/utils.js +3 -4
  28. package/package.json +18 -16
  29. package/types/aggregate.d.ts +3 -4
  30. package/types/callback.d.ts +8 -0
  31. package/types/collection.d.ts +46 -0
  32. package/types/connection.d.ts +92 -72
  33. package/types/document.d.ts +1 -1
  34. package/types/error.d.ts +5 -1
  35. package/types/helpers.d.ts +33 -0
  36. package/types/index.d.ts +32 -1859
  37. package/types/indizes.d.ts +98 -0
  38. package/types/middlewares.d.ts +14 -0
  39. package/types/models.d.ts +419 -0
  40. package/types/populate.d.ts +40 -0
  41. package/types/query.d.ts +637 -0
  42. package/types/schematypes.d.ts +418 -0
  43. package/types/session.d.ts +36 -0
  44. package/types/types.d.ts +102 -0
  45. package/types/utility.d.ts +13 -0
  46. package/types/validation.d.ts +32 -0
  47. package/.lgtm.yml +0 -3
package/lgtm.yml ADDED
@@ -0,0 +1,12 @@
1
+ path_classifiers:
2
+ src:
3
+ - lib
4
+ types:
5
+ - types
6
+ test:
7
+ - test
8
+ docs:
9
+ - docs
10
+ queries:
11
+ - exclude: "*"
12
+ - include: lib
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const isBsonType = require('../helpers/isBsonType');
3
4
  const ObjectId = require('../driver').get().ObjectId;
4
5
 
5
6
  module.exports = function castObjectId(value) {
@@ -7,12 +8,12 @@ module.exports = function castObjectId(value) {
7
8
  return value;
8
9
  }
9
10
 
10
- if (value instanceof ObjectId) {
11
+ if (isBsonType(value, 'ObjectID')) {
11
12
  return value;
12
13
  }
13
14
 
14
15
  if (value._id) {
15
- if (value._id instanceof ObjectId) {
16
+ if (isBsonType(value._id, 'ObjectID')) {
16
17
  return value._id;
17
18
  }
18
19
  if (value._id.toString instanceof Function) {
package/lib/connection.js CHANGED
@@ -7,13 +7,13 @@
7
7
  const ChangeStream = require('./cursor/ChangeStream');
8
8
  const EventEmitter = require('events').EventEmitter;
9
9
  const Schema = require('./schema');
10
- const Collection = require('./driver').get().Collection;
11
10
  const STATES = require('./connectionstate');
12
11
  const MongooseError = require('./error/index');
13
12
  const SyncIndexesError = require('./error/syncIndexes');
14
13
  const PromiseProvider = require('./promise_provider');
15
14
  const ServerSelectionError = require('./error/serverSelection');
16
15
  const applyPlugins = require('./helpers/schema/applyPlugins');
16
+ const driver = require('./driver');
17
17
  const promiseOrCallback = require('./helpers/promiseOrCallback');
18
18
  const get = require('./helpers/get');
19
19
  const immediate = require('./helpers/immediate');
@@ -548,7 +548,7 @@ Connection.prototype.dropDatabase = _wrapConnHelper(function dropDatabase(cb) {
548
548
  // If `dropDatabase()` is called, this model's collection will not be
549
549
  // init-ed. It is sufficiently common to call `dropDatabase()` after
550
550
  // `mongoose.connect()` but before creating models that we want to
551
- // support this. See gh-6967
551
+ // support this. See gh-6796
552
552
  for (const name of Object.keys(this.models)) {
553
553
  delete this.models[name].$init;
554
554
  }
@@ -1026,6 +1026,7 @@ Connection.prototype.collection = function(name, options) {
1026
1026
  };
1027
1027
  options = Object.assign({}, defaultOptions, options ? utils.clone(options) : {});
1028
1028
  options.$wasForceClosed = this.$wasForceClosed;
1029
+ const Collection = driver.get().Collection;
1029
1030
  if (!(name in this.collections)) {
1030
1031
  this.collections[name] = new Collection(name, this, options);
1031
1032
  }
package/lib/document.js CHANGED
@@ -1323,6 +1323,10 @@ Document.prototype.$set = function $set(path, val, type, options) {
1323
1323
 
1324
1324
  if (!schema) {
1325
1325
  this.$__set(pathToMark, path, options, constructing, parts, schema, val, priorVal);
1326
+
1327
+ if (pathType === 'nested' && val == null) {
1328
+ cleanModifiedSubpaths(this, path);
1329
+ }
1326
1330
  return this;
1327
1331
  }
1328
1332
 
@@ -1374,7 +1378,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1374
1378
  })();
1375
1379
 
1376
1380
  let didPopulate = false;
1377
- if (refMatches && val instanceof Document) {
1381
+ if (refMatches && val instanceof Document && (!val.$__.wasPopulated || utils.deepEqual(val.$__.wasPopulated.value, val._id))) {
1378
1382
  const unpopulatedValue = (schema && schema.$isSingleNested) ? schema.cast(val, this) : val._id;
1379
1383
  this.$populated(path, unpopulatedValue, { [populateModelSymbol]: val.constructor });
1380
1384
  val.$__.wasPopulated = { value: unpopulatedValue };
@@ -3460,9 +3464,9 @@ Document.prototype.$toObject = function(options, json) {
3460
3464
 
3461
3465
  const path = json ? 'toJSON' : 'toObject';
3462
3466
  const baseOptions = this.constructor &&
3463
- this.constructor.base &&
3464
- this.constructor.base.options &&
3465
- get(this.constructor.base.options, path) || {};
3467
+ this.constructor.base &&
3468
+ this.constructor.base.options &&
3469
+ get(this.constructor.base.options, path) || {};
3466
3470
  const schemaOptions = this.$__schema && this.$__schema.options || {};
3467
3471
  // merge base default options with Schema's set default options if available.
3468
3472
  // `clone` is necessary here because `utils.options` directly modifies the second input.
@@ -3470,8 +3474,8 @@ Document.prototype.$toObject = function(options, json) {
3470
3474
  defaultOptions = utils.options(defaultOptions, clone(schemaOptions[path] || {}));
3471
3475
 
3472
3476
  // If options do not exist or is not an object, set it to empty object
3473
- options = utils.isPOJO(options) ? clone(options) : {};
3474
- options._calledWithOptions = options._calledWithOptions || clone(options);
3477
+ options = utils.isPOJO(options) ? { ...options } : {};
3478
+ options._calledWithOptions = options._calledWithOptions || { ...options };
3475
3479
 
3476
3480
  let _minimize;
3477
3481
  if (options._calledWithOptions.minimize != null) {
@@ -3495,11 +3499,12 @@ Document.prototype.$toObject = function(options, json) {
3495
3499
  // `clone()` will recursively call `$toObject()` on embedded docs, so we
3496
3500
  // need the original options the user passed in, plus `_isNested` and
3497
3501
  // `_parentOptions` for checking whether we need to depopulate.
3498
- const cloneOptions = Object.assign(utils.clone(options), {
3502
+ const cloneOptions = Object.assign({}, options, {
3499
3503
  _isNested: true,
3500
3504
  json: json,
3501
3505
  minimize: _minimize,
3502
- flattenMaps: flattenMaps
3506
+ flattenMaps: flattenMaps,
3507
+ _seen: (options && options._seen) || new Map()
3503
3508
  });
3504
3509
 
3505
3510
  if (utils.hasUserDefinedProperty(options, 'getters')) {
@@ -4222,8 +4227,10 @@ Document.prototype.populate = function populate() {
4222
4227
  * @api public
4223
4228
  * @return {Array<Document>} array of populated documents. Empty array if there are no populated documents associated with this document.
4224
4229
  * @memberOf Document
4230
+ * @method $getPopulatedDocs
4225
4231
  * @instance
4226
4232
  */
4233
+
4227
4234
  Document.prototype.$getPopulatedDocs = function $getPopulatedDocs() {
4228
4235
  let keys = [];
4229
4236
  if (this.$__.populated != null) {
@@ -5,11 +5,11 @@
5
5
  * Mongoose-specific errors.
6
6
  *
7
7
  * #### Example:
8
- * const Model = mongoose.model('Test', new Schema({ answer: Number }));
8
+ * const Model = mongoose.model('Test', new mongoose.Schema({ answer: Number }));
9
9
  * const doc = new Model({ answer: 'not a number' });
10
10
  * const err = doc.validateSync();
11
11
  *
12
- * err instanceof mongoose.Error; // true
12
+ * err instanceof mongoose.Error.ValidationError; // true
13
13
  *
14
14
  * @constructor Error
15
15
  * @param {String} msg Error message
@@ -77,7 +77,7 @@ function clone(obj, options, isArrayChild) {
77
77
  }
78
78
  }
79
79
 
80
- if (obj instanceof ObjectId) {
80
+ if (isBsonType(obj, 'ObjectID')) {
81
81
  return new ObjectId(obj.id);
82
82
  }
83
83
 
@@ -118,9 +118,16 @@ module.exports = clone;
118
118
 
119
119
  function cloneObject(obj, options, isArrayChild) {
120
120
  const minimize = options && options.minimize;
121
+ const omitUndefined = options && options.omitUndefined;
122
+ const seen = options && options._seen;
121
123
  const ret = {};
122
124
  let hasKeys;
123
125
 
126
+ if (seen && seen.has(obj)) {
127
+ return seen.get(obj);
128
+ } else if (seen) {
129
+ seen.set(obj, ret);
130
+ }
124
131
  if (trustedSymbol in obj) {
125
132
  ret[trustedSymbol] = obj[trustedSymbol];
126
133
  }
@@ -138,7 +145,7 @@ function cloneObject(obj, options, isArrayChild) {
138
145
  // Don't pass `isArrayChild` down
139
146
  const val = clone(obj[key], options, false);
140
147
 
141
- if (minimize === false && typeof val === 'undefined') {
148
+ if ((minimize === false || omitUndefined) && typeof val === 'undefined') {
142
149
  delete ret[key];
143
150
  } else if (minimize !== true || (typeof val !== 'undefined')) {
144
151
  hasKeys || (hasKeys = true);
@@ -5,8 +5,7 @@
5
5
  */
6
6
 
7
7
  const Binary = require('../driver').get().Binary;
8
- const Decimal128 = require('../types/decimal128');
9
- const ObjectId = require('../types/objectid');
8
+ const isBsonType = require('./isBsonType');
10
9
  const isMongooseObject = require('./isMongooseObject');
11
10
 
12
11
  exports.flatten = flatten;
@@ -99,9 +98,9 @@ function shouldFlatten(val) {
99
98
  return val &&
100
99
  typeof val === 'object' &&
101
100
  !(val instanceof Date) &&
102
- !(val instanceof ObjectId) &&
101
+ !isBsonType(val, 'ObjectID') &&
103
102
  (!Array.isArray(val) || val.length !== 0) &&
104
103
  !(val instanceof Buffer) &&
105
- !(val instanceof Decimal128) &&
104
+ !isBsonType(val, 'Decimal128') &&
106
105
  !(val instanceof Binary);
107
106
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const ObjectId = require('../../types/objectid');
3
+ const isBsonType = require('../isBsonType');
4
4
 
5
5
  module.exports = function areDiscriminatorValuesEqual(a, b) {
6
6
  if (typeof a === 'string' && typeof b === 'string') {
@@ -9,7 +9,7 @@ module.exports = function areDiscriminatorValuesEqual(a, b) {
9
9
  if (typeof a === 'number' && typeof b === 'number') {
10
10
  return a === b;
11
11
  }
12
- if (a instanceof ObjectId && b instanceof ObjectId) {
12
+ if (isBsonType(a, 'ObjectID') && isBsonType(b, 'ObjectID')) {
13
13
  return a.toString() === b.toString();
14
14
  }
15
15
  return false;
@@ -1,13 +1,15 @@
1
1
  'use strict';
2
2
 
3
- const get = require('./get');
4
-
5
3
  /*!
6
4
  * Get the bson type, if it exists
7
5
  */
8
6
 
9
7
  function isBsonType(obj, typename) {
10
- return get(obj, '_bsontype', void 0) === typename;
8
+ return (
9
+ typeof obj === 'object' &&
10
+ obj !== null &&
11
+ obj._bsontype === typename
12
+ );
11
13
  }
12
14
 
13
15
  module.exports = isBsonType;
@@ -1,14 +1,25 @@
1
1
  'use strict';
2
2
 
3
+ const specialProperties = require('../specialProperties');
4
+
5
+
3
6
  module.exports = function setDottedPath(obj, path, val) {
4
7
  if (path.indexOf('.') === -1) {
8
+ if (specialProperties.has(path)) {
9
+ return;
10
+ }
11
+
5
12
  obj[path] = val;
6
13
  return;
7
14
  }
8
15
  const parts = path.split('.');
16
+
9
17
  const last = parts.pop();
10
18
  let cur = obj;
11
19
  for (const part of parts) {
20
+ if (specialProperties.has(part)) {
21
+ continue;
22
+ }
12
23
  if (cur[part] == null) {
13
24
  cur[part] = {};
14
25
  }
@@ -16,5 +27,7 @@ module.exports = function setDottedPath(obj, path, val) {
16
27
  cur = cur[part];
17
28
  }
18
29
 
19
- cur[last] = val;
30
+ if (!specialProperties.has(last)) {
31
+ cur[last] = val;
32
+ }
20
33
  };
@@ -8,6 +8,19 @@ module.exports = function isAtlas(topologyDescription) {
8
8
  }
9
9
 
10
10
  const hostnames = Array.from(topologyDescription.servers.keys());
11
- return hostnames.length > 0 &&
12
- hostnames.every(host => host.endsWith('.mongodb.net:27017'));
11
+
12
+ if (hostnames.length === 0) {
13
+ return false;
14
+ }
15
+
16
+ for (let i = 0, il = hostnames.length; i < il; ++i) {
17
+ const url = new URL(hostnames[i]);
18
+ if (
19
+ url.hostname.endsWith('.mongodb.net') === false ||
20
+ url.port !== '27017'
21
+ ) {
22
+ return false;
23
+ }
24
+ }
25
+ return true;
13
26
  };
@@ -61,6 +61,8 @@ function applyTimestampsToChildren(now, update, schema) {
61
61
  if (createdAt != null) {
62
62
  subdoc[createdAt] = now;
63
63
  }
64
+
65
+ applyTimestampsToChildren(now, subdoc, $path.schema);
64
66
  });
65
67
  } else {
66
68
  if (updatedAt != null) {
@@ -69,6 +71,8 @@ function applyTimestampsToChildren(now, update, schema) {
69
71
  if (createdAt != null) {
70
72
  op[key][createdAt] = now;
71
73
  }
74
+
75
+ applyTimestampsToChildren(now, op[key], $path.schema);
72
76
  }
73
77
  }
74
78
  }
package/lib/index.js CHANGED
@@ -34,6 +34,7 @@ const PromiseProvider = require('./promise_provider');
34
34
  const shardingPlugin = require('./plugins/sharding');
35
35
  const trusted = require('./helpers/query/trusted').trusted;
36
36
  const sanitizeFilter = require('./helpers/query/sanitizeFilter');
37
+ const isBsonType = require('./helpers/isBsonType');
37
38
 
38
39
  const defaultMongooseSymbol = Symbol.for('mongoose:default');
39
40
 
@@ -153,7 +154,7 @@ Mongoose.prototype.driver = driver;
153
154
  * mongoose.set('debug', function(collectionName, methodName, ...methodArgs) {}); // use custom function to log collection methods + arguments
154
155
  *
155
156
  * Currently supported options are:
156
- * - 'debug': If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arugments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
157
+ * - 'debug': If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arguments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
157
158
  * - 'returnOriginal': If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`, `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to setting the `new` option to `true` for `findOneAndX()` calls by default. Read our [`findOneAndUpdate()` tutorial](/docs/tutorials/findoneandupdate.html) for more information.
158
159
  * - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
159
160
  * - 'cloneSchemas': false by default. Set to `true` to `clone()` all schemas before compiling into a model.
@@ -274,6 +275,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
274
275
  Mongoose.prototype.createConnection = function(uri, options, callback) {
275
276
  const _mongoose = this instanceof Mongoose ? this : mongoose;
276
277
 
278
+ const Connection = driver.get().getConnection();
277
279
  const conn = new Connection(_mongoose);
278
280
  if (typeof options === 'function') {
279
281
  callback = options;
@@ -995,8 +997,7 @@ Mongoose.prototype.isValidObjectId = function(v) {
995
997
  */
996
998
 
997
999
  Mongoose.prototype.isObjectIdOrHexString = function(v) {
998
- const _mongoose = this instanceof Mongoose ? this : mongoose;
999
- return v instanceof _mongoose.Types.ObjectId || (typeof v === 'string' && objectIdHexRegexp.test(v));
1000
+ return isBsonType(v, 'ObjectID') || (typeof v === 'string' && objectIdHexRegexp.test(v));
1000
1001
  };
1001
1002
 
1002
1003
  /**
package/lib/model.js CHANGED
@@ -768,6 +768,7 @@ Model.prototype.$__delta = function() {
768
768
  transform: false,
769
769
  virtuals: false,
770
770
  getters: false,
771
+ omitUndefined: true,
771
772
  _isNested: true
772
773
  });
773
774
  operand(this, where, delta, data, value);
@@ -1488,61 +1489,68 @@ Model.syncIndexes = function syncIndexes(options, callback) {
1488
1489
  * the result of this function would be the result of
1489
1490
  * Model.syncIndexes().
1490
1491
  *
1491
- * @param {Object} options not used at all.
1492
+ * @param {Object} [options]
1492
1493
  * @param {Function} callback optional callback
1493
- * @returns {Promise} which containts an object, {toDrop, toCreate}, which
1494
- * are indexes that would be dropped in mongodb and indexes that would be created in mongodb.
1494
+ * @returns {Promise} which contains an object, {toDrop, toCreate}, which
1495
+ * are indexes that would be dropped in MongoDB and indexes that would be created in MongoDB.
1495
1496
  */
1496
1497
 
1497
1498
  Model.diffIndexes = function diffIndexes(options, callback) {
1499
+ if (typeof options === 'function') {
1500
+ callback = options;
1501
+ options = null;
1502
+ }
1498
1503
  const toDrop = [];
1499
1504
  const toCreate = [];
1500
1505
  callback = this.$handleCallbackError(callback);
1501
1506
  return this.db.base._promiseOrCallback(callback, cb => {
1502
1507
  cb = this.$wrapCallback(cb);
1503
- this.listIndexes((err, indexes) => {
1504
- if (indexes === undefined) {
1505
- indexes = [];
1508
+ this.listIndexes((err, dbIndexes) => {
1509
+ if (dbIndexes === undefined) {
1510
+ dbIndexes = [];
1506
1511
  }
1507
- const schemaIndexes = this.schema.indexes();
1508
- // Iterate through the indexes created in mongodb and
1509
- // compare against the indexes in the schema.
1510
- for (const index of indexes) {
1512
+ dbIndexes = getRelatedDBIndexes(this, dbIndexes);
1513
+ const schemaIndexes = getRelatedSchemaIndexes(this, this.schema.indexes());
1514
+
1515
+ for (const dbIndex of dbIndexes) {
1511
1516
  let found = false;
1512
1517
  // Never try to drop `_id` index, MongoDB server doesn't allow it
1513
- if (isDefaultIdIndex(index)) {
1518
+ if (isDefaultIdIndex(dbIndex)) {
1514
1519
  continue;
1515
1520
  }
1516
1521
 
1517
- for (const schemaIndex of schemaIndexes) {
1518
- const key = schemaIndex[0];
1519
- const options = decorateDiscriminatorIndexOptions(this.schema, utils.clone(schemaIndex[1]));
1520
- if (isIndexEqual(key, options, index)) {
1522
+ for (const [schemaIndexKeysObject, schemaIndexOptions] of schemaIndexes) {
1523
+ const options = decorateDiscriminatorIndexOptions(this.schema, utils.clone(schemaIndexOptions));
1524
+ applySchemaCollation(schemaIndexKeysObject, options, this.schema.options);
1525
+
1526
+ if (isIndexEqual(schemaIndexKeysObject, options, dbIndex)) {
1521
1527
  found = true;
1522
1528
  }
1523
1529
  }
1524
1530
 
1525
1531
  if (!found) {
1526
- toDrop.push(index.name);
1532
+ toDrop.push(dbIndex.name);
1527
1533
  }
1528
1534
  }
1529
1535
  // Iterate through the indexes created on the schema and
1530
1536
  // compare against the indexes in mongodb.
1531
- for (const schemaIndex of schemaIndexes) {
1532
- let found = false;
1533
- const key = schemaIndex[0];
1534
- const options = decorateDiscriminatorIndexOptions(this.schema, utils.clone(schemaIndex[1]));
1535
- for (const index of indexes) {
1536
- if (isDefaultIdIndex(index)) {
1537
- continue;
1537
+ if (!options || options.toCreate !== false) {
1538
+ for (const schemaIndex of schemaIndexes) {
1539
+ let found = false;
1540
+ const key = schemaIndex[0];
1541
+ const options = decorateDiscriminatorIndexOptions(this.schema, utils.clone(schemaIndex[1]));
1542
+ for (const index of dbIndexes) {
1543
+ if (isDefaultIdIndex(index)) {
1544
+ continue;
1545
+ }
1546
+ if (isIndexEqual(key, options, index)) {
1547
+ found = true;
1548
+ }
1538
1549
  }
1539
- if (isIndexEqual(key, options, index)) {
1540
- found = true;
1550
+ if (!found) {
1551
+ toCreate.push(key);
1541
1552
  }
1542
1553
  }
1543
- if (!found) {
1544
- toCreate.push(key);
1545
- }
1546
1554
  }
1547
1555
  cb(null, { toDrop, toCreate });
1548
1556
  });
@@ -1568,36 +1576,12 @@ Model.cleanIndexes = function cleanIndexes(callback) {
1568
1576
  return this.db.base._promiseOrCallback(callback, cb => {
1569
1577
  const collection = this.$__collection;
1570
1578
 
1571
- this.listIndexes((err, dbIndexes) => {
1579
+ this.diffIndexes({ toCreate: false }, (err, res) => {
1572
1580
  if (err != null) {
1573
1581
  return cb(err);
1574
1582
  }
1575
1583
 
1576
- dbIndexes = getRelatedDBIndexes(this, dbIndexes);
1577
- const schemaIndexes = getRelatedSchemaIndexes(this, this.schema.indexes());
1578
-
1579
- const toDrop = [];
1580
-
1581
- for (const dbIndex of dbIndexes) {
1582
- let found = false;
1583
- // Never try to drop `_id` index, MongoDB server doesn't allow it
1584
- if (isDefaultIdIndex(dbIndex)) {
1585
- continue;
1586
- }
1587
-
1588
- for (const [schemaIndexKeysObject, schemaIndexOptions] of schemaIndexes) {
1589
- const options = decorateDiscriminatorIndexOptions(this.schema, utils.clone(schemaIndexOptions));
1590
- applySchemaCollation(schemaIndexKeysObject, options, this.schema.options);
1591
-
1592
- if (isIndexEqual(schemaIndexKeysObject, options, dbIndex)) {
1593
- found = true;
1594
- }
1595
- }
1596
-
1597
- if (!found) {
1598
- toDrop.push(dbIndex.name);
1599
- }
1600
- }
1584
+ const toDrop = res.toDrop;
1601
1585
 
1602
1586
  if (toDrop.length === 0) {
1603
1587
  return cb(null, []);
package/lib/query.js CHANGED
@@ -124,7 +124,10 @@ function Query(conditions, options, model, collection) {
124
124
  }
125
125
 
126
126
  // inherit mquery
127
- mquery.call(this, this.mongooseCollection, options);
127
+ mquery.call(this, null, options);
128
+ if (collection) {
129
+ this.collection(collection);
130
+ }
128
131
 
129
132
  if (conditions) {
130
133
  this.find(conditions);
@@ -226,7 +226,9 @@ exports.applyPaths = function applyPaths(fields, schema) {
226
226
  const addedPaths = [];
227
227
  schema.eachPath(function(path, type) {
228
228
  if (prefix) path = prefix + '.' + path;
229
-
229
+ if (type.$isSchemaMap || path.endsWith('.$*')) {
230
+ return;
231
+ }
230
232
  let addedPath = analyzePath(path, type);
231
233
  // arrays
232
234
  if (addedPath == null && !Array.isArray(type) && type.$isMongooseArray && !type.$isMongooseDocumentArray) {
@@ -248,7 +250,6 @@ exports.applyPaths = function applyPaths(fields, schema) {
248
250
  }
249
251
  }
250
252
  });
251
-
252
253
  stack.pop();
253
254
  return addedPaths;
254
255
  }
@@ -6,9 +6,9 @@
6
6
 
7
7
  const SchemaType = require('../schematype');
8
8
  const CastError = SchemaType.CastError;
9
- const Decimal128Type = require('../types/decimal128');
10
9
  const castDecimal128 = require('../cast/decimal128');
11
10
  const utils = require('../utils');
11
+ const isBsonType = require('../helpers/isBsonType');
12
12
 
13
13
  /**
14
14
  * Decimal128 SchemaType constructor.
@@ -105,7 +105,7 @@ Decimal128.cast = function cast(caster) {
105
105
  */
106
106
 
107
107
  Decimal128._defaultCaster = v => {
108
- if (v != null && !(v instanceof Decimal128Type)) {
108
+ if (v != null && !isBsonType(v, 'Decimal128')) {
109
109
  throw new Error();
110
110
  }
111
111
  return v;
@@ -115,7 +115,7 @@ Decimal128._defaultCaster = v => {
115
115
  * ignore
116
116
  */
117
117
 
118
- Decimal128._checkRequired = v => v instanceof Decimal128Type;
118
+ Decimal128._checkRequired = v => isBsonType(v, 'Decimal128');
119
119
 
120
120
  /**
121
121
  * Override the function the required validator uses to check whether a string
@@ -164,7 +164,7 @@ Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
164
164
 
165
165
  Decimal128.prototype.cast = function(value, doc, init) {
166
166
  if (SchemaType._isRef(this, value, doc, init)) {
167
- if (value instanceof Decimal128Type) {
167
+ if (isBsonType(value, 'Decimal128')) {
168
168
  return value;
169
169
  }
170
170
 
package/lib/schema/map.js CHANGED
@@ -69,6 +69,14 @@ class Map extends SchemaType {
69
69
  }
70
70
  }
71
71
 
72
+ /**
73
+ * This schema type's name, to defend against minifiers that mangle
74
+ * function names.
75
+ *
76
+ * @api public
77
+ */
78
+ Map.schemaName = 'Map';
79
+
72
80
  Map.prototype.OptionsConstructor = SchemaMapOptions;
73
81
 
74
82
  Map.defaultOptions = {};
@@ -9,6 +9,7 @@ const SchemaType = require('../schematype');
9
9
  const castObjectId = require('../cast/objectid');
10
10
  const getConstructorName = require('../helpers/getConstructorName');
11
11
  const oid = require('../types/objectid');
12
+ const isBsonType = require('../helpers/isBsonType');
12
13
  const utils = require('../utils');
13
14
 
14
15
  const CastError = SchemaType.CastError;
@@ -113,7 +114,7 @@ ObjectId.prototype.auto = function(turnOn) {
113
114
  * ignore
114
115
  */
115
116
 
116
- ObjectId._checkRequired = v => v instanceof oid;
117
+ ObjectId._checkRequired = v => isBsonType(v, 'ObjectID');
117
118
 
118
119
  /*!
119
120
  * ignore
@@ -161,7 +162,7 @@ ObjectId.cast = function cast(caster) {
161
162
  */
162
163
 
163
164
  ObjectId._defaultCaster = v => {
164
- if (!(v instanceof oid)) {
165
+ if (!(isBsonType(v, 'ObjectID'))) {
165
166
  throw new Error(v + ' is not an instance of ObjectId');
166
167
  }
167
168
  return v;
@@ -221,7 +222,7 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
221
222
  */
222
223
 
223
224
  ObjectId.prototype.cast = function(value, doc, init) {
224
- if (!(value instanceof oid) && SchemaType._isRef(this, value, doc, init)) {
225
+ if (!(isBsonType(value, 'ObjectID')) && SchemaType._isRef(this, value, doc, init)) {
225
226
  // wait! we may need to cast this to a document
226
227
  if ((getConstructorName(value) || '').toLowerCase() === 'objectid') {
227
228
  return new oid(value.toHexString());
@@ -4,12 +4,12 @@
4
4
  * Module dependencies.
5
5
  */
6
6
 
7
- const { BSONRegExp } = require('bson');
8
7
  const SchemaType = require('../schematype');
9
8
  const MongooseError = require('../error/index');
10
9
  const SchemaStringOptions = require('../options/SchemaStringOptions');
11
10
  const castString = require('../cast/string');
12
11
  const utils = require('../utils');
12
+ const isBsonType = require('../helpers/isBsonType');
13
13
 
14
14
  const CastError = SchemaType.CastError;
15
15
 
@@ -677,7 +677,7 @@ SchemaString.prototype.castForQuery = function($conditional, val) {
677
677
  return handler.call(this, val);
678
678
  }
679
679
  val = $conditional;
680
- if (Object.prototype.toString.call(val) === '[object RegExp]' || val instanceof BSONRegExp) {
680
+ if (Object.prototype.toString.call(val) === '[object RegExp]' || isBsonType(val, 'BSONRegExp')) {
681
681
  return val;
682
682
  }
683
683