mongoose 6.1.9 → 6.2.2

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 (76) hide show
  1. package/.eslintrc.json +154 -0
  2. package/CHANGELOG.md +59 -0
  3. package/dist/browser.umd.js +233 -222
  4. package/index.js +5 -1
  5. package/lib/aggregate.js +23 -28
  6. package/lib/browserDocument.js +1 -1
  7. package/lib/cast/number.js +2 -3
  8. package/lib/cast.js +9 -7
  9. package/lib/connection.js +76 -24
  10. package/lib/cursor/AggregationCursor.js +12 -7
  11. package/lib/cursor/QueryCursor.js +11 -6
  12. package/lib/document.js +107 -107
  13. package/lib/drivers/node-mongodb-native/collection.js +12 -4
  14. package/lib/drivers/node-mongodb-native/connection.js +11 -0
  15. package/lib/error/cast.js +3 -2
  16. package/lib/error/index.js +11 -0
  17. package/lib/error/syncIndexes.js +30 -0
  18. package/lib/helpers/clone.js +51 -29
  19. package/lib/helpers/common.js +2 -2
  20. package/lib/helpers/cursor/eachAsync.js +18 -15
  21. package/lib/helpers/document/compile.js +7 -4
  22. package/lib/helpers/getFunctionName.js +6 -4
  23. package/lib/helpers/isMongooseObject.js +9 -8
  24. package/lib/helpers/isObject.js +4 -4
  25. package/lib/helpers/model/discriminator.js +2 -1
  26. package/lib/helpers/path/parentPaths.js +10 -5
  27. package/lib/helpers/populate/assignRawDocsToIdStructure.js +4 -2
  28. package/lib/helpers/populate/assignVals.js +8 -4
  29. package/lib/helpers/populate/getModelsMapForPopulate.js +4 -4
  30. package/lib/helpers/populate/markArraySubdocsPopulated.js +3 -1
  31. package/lib/helpers/populate/modelNamesFromRefPath.js +4 -3
  32. package/lib/helpers/printJestWarning.js +2 -2
  33. package/lib/helpers/projection/applyProjection.js +77 -0
  34. package/lib/helpers/projection/hasIncludedChildren.js +36 -0
  35. package/lib/helpers/projection/isExclusive.js +5 -2
  36. package/lib/helpers/projection/isInclusive.js +5 -1
  37. package/lib/helpers/query/cast$expr.js +279 -0
  38. package/lib/helpers/query/castUpdate.js +6 -2
  39. package/lib/helpers/query/isOperator.js +5 -2
  40. package/lib/helpers/schema/applyPlugins.js +11 -0
  41. package/lib/helpers/schema/getPath.js +4 -2
  42. package/lib/helpers/timestamps/setupTimestamps.js +3 -8
  43. package/lib/index.js +28 -26
  44. package/lib/internal.js +1 -1
  45. package/lib/model.js +161 -122
  46. package/lib/options/SchemaTypeOptions.js +1 -1
  47. package/lib/plugins/trackTransaction.js +5 -4
  48. package/lib/query.js +159 -146
  49. package/lib/queryhelpers.js +10 -10
  50. package/lib/schema/SubdocumentPath.js +4 -3
  51. package/lib/schema/array.js +30 -21
  52. package/lib/schema/buffer.js +1 -1
  53. package/lib/schema/date.js +1 -1
  54. package/lib/schema/decimal128.js +1 -1
  55. package/lib/schema/documentarray.js +9 -11
  56. package/lib/schema/number.js +1 -1
  57. package/lib/schema/objectid.js +2 -2
  58. package/lib/schema/string.js +4 -4
  59. package/lib/schema.js +9 -8
  60. package/lib/schematype.js +77 -30
  61. package/lib/types/ArraySubdocument.js +2 -1
  62. package/lib/types/DocumentArray/index.js +10 -27
  63. package/lib/types/DocumentArray/isMongooseDocumentArray.js +5 -0
  64. package/lib/types/DocumentArray/methods/index.js +15 -3
  65. package/lib/types/array/index.js +22 -21
  66. package/lib/types/array/isMongooseArray.js +5 -0
  67. package/lib/types/array/methods/index.js +22 -23
  68. package/lib/types/buffer.js +3 -3
  69. package/lib/types/map.js +2 -3
  70. package/lib/utils.js +10 -7
  71. package/package.json +19 -151
  72. package/tools/repl.js +1 -1
  73. package/tsconfig.json +8 -0
  74. package/types/PipelineStage.d.ts +272 -0
  75. package/{index.d.ts → types/index.d.ts} +156 -357
  76. package/lib/types/array/ArrayWrapper.js +0 -981
package/lib/model.js CHANGED
@@ -25,6 +25,7 @@ const ParallelSaveError = require('./error/parallelSave');
25
25
  const applyQueryMiddleware = require('./helpers/query/applyQueryMiddleware');
26
26
  const applyHooks = require('./helpers/model/applyHooks');
27
27
  const applyMethods = require('./helpers/model/applyMethods');
28
+ const applyProjection = require('./helpers/projection/applyProjection');
28
29
  const applyStaticHooks = require('./helpers/model/applyStaticHooks');
29
30
  const applyStatics = require('./helpers/model/applyStatics');
30
31
  const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
@@ -48,6 +49,7 @@ const modifiedPaths = require('./helpers/update/modifiedPaths');
48
49
  const parallelLimit = require('./helpers/parallelLimit');
49
50
  const prepareDiscriminatorPipeline = require('./helpers/aggregate/prepareDiscriminatorPipeline');
50
51
  const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField');
52
+ const setDottedPath = require('./helpers/path/setDottedPath');
51
53
  const util = require('util');
52
54
  const utils = require('./utils');
53
55
 
@@ -90,7 +92,7 @@ const saveToObjectOptions = Object.assign({}, internalToObjectOptions, {
90
92
  * @param {Object} doc values for initial set
91
93
  * @param [fields] optional object containing the fields that were selected in the query which returned this document. You do **not** need to set this parameter to ensure Mongoose handles your [query projection](./api.html#query_Query-select).
92
94
  * @param {Boolean} [skipId=false] optional boolean. If true, mongoose doesn't add an `_id` field to the document.
93
- * @inherits Document http://mongoosejs.com/docs/api/document.html
95
+ * @inherits Document https://mongoosejs.com/docs/api/document.html
94
96
  * @event `error`: If listening to this event, 'error' is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
95
97
  * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
96
98
  * @event `index-single-start`: Emitted when an individual index starts within `Model#ensureIndexes`. The fields and options being used to build the index are also passed with the event.
@@ -242,7 +244,7 @@ Model.prototype.$__handleSave = function(options, callback) {
242
244
  let saveOptions = {};
243
245
 
244
246
  applyWriteConcern(this.$__schema, options);
245
- if (typeof options.writeConcern != 'undefined') {
247
+ if (typeof options.writeConcern !== 'undefined') {
246
248
  saveOptions.writeConcern = {};
247
249
  if ('w' in options.writeConcern) {
248
250
  saveOptions.writeConcern.w = options.writeConcern.w;
@@ -344,17 +346,12 @@ Model.prototype.$__handleSave = function(options, callback) {
344
346
  where[key] = val;
345
347
  }
346
348
  }
347
- this.constructor.exists(where, optionsWithCustomValues).
348
- then((documentExists) => {
349
- if (!documentExists) {
350
- const matchedCount = 0;
351
- return callback(null, { $where: where, matchedCount });
352
- }
353
-
354
- const matchedCount = 1;
349
+ this.constructor.exists(where, optionsWithCustomValues)
350
+ .then(documentExists => {
351
+ const matchedCount = !documentExists ? 0 : 1;
355
352
  callback(null, { $where: where, matchedCount });
356
- }).
357
- catch(callback);
353
+ })
354
+ .catch(callback);
358
355
  return;
359
356
  }
360
357
 
@@ -379,7 +376,12 @@ Model.prototype.$__save = function(options, callback) {
379
376
  });
380
377
  }
381
378
  let numAffected = 0;
382
- if (get(options, 'safe.w') !== 0 && get(options, 'w') !== 0) {
379
+ const writeConcern = options != null ?
380
+ options.writeConcern != null ?
381
+ options.writeConcern.w :
382
+ options.w :
383
+ 0;
384
+ if (writeConcern !== 0) {
383
385
  // Skip checking if write succeeded if writeConcern is set to
384
386
  // unacknowledged writes, because otherwise `numAffected` will always be 0
385
387
  if (result != null) {
@@ -391,8 +393,10 @@ Model.prototype.$__save = function(options, callback) {
391
393
  numAffected = result;
392
394
  }
393
395
  }
396
+
397
+ const versionBump = this.$__.version || this.$__schema.options.optimisticConcurrency;
394
398
  // was this an update that required a version bump?
395
- if (this.$__.version && !this.$__.inserting) {
399
+ if (versionBump && !this.$__.inserting) {
396
400
  const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
397
401
  this.$__.version = undefined;
398
402
  const key = this.$__schema.options.versionKey;
@@ -459,7 +463,7 @@ function generateVersionError(doc, modifiedPaths) {
459
463
  *
460
464
  * @param {Object} [options] options optional options
461
465
  * @param {Session} [options.session=null] the [session](https://docs.mongodb.com/manual/reference/server-sessions/) associated with this save operation. If not specified, defaults to the [document's associated session](api.html#document_Document-$session).
462
- * @param {Object} [options.safe] (DEPRECATED) overrides [schema's safe option](http://mongoosejs.com//docs/guide.html#safe). Use the `w` option instead.
466
+ * @param {Object} [options.safe] (DEPRECATED) overrides [schema's safe option](https://mongoosejs.com//docs/guide.html#safe). Use the `w` option instead.
463
467
  * @param {Boolean} [options.validateBeforeSave] set to false to save without validating.
464
468
  * @param {Boolean} [options.validateModifiedOnly=false] if `true`, Mongoose will only validate modified paths, as opposed to modified paths and `required` paths.
465
469
  * @param {Number|String} [options.w] set the [write concern](https://docs.mongodb.com/manual/reference/write-concern/#w-option). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern)
@@ -471,7 +475,7 @@ function generateVersionError(doc, modifiedPaths) {
471
475
  * @throws {DocumentNotFoundError} if this [save updates an existing document](api.html#document_Document-isNew) but the document doesn't exist in the database. For example, you will get this error if the document is [deleted between when you retrieved the document and when you saved it](documents.html#updating).
472
476
  * @return {Promise|undefined} Returns undefined if used with callback or a Promise otherwise.
473
477
  * @api public
474
- * @see middleware http://mongoosejs.com/docs/middleware.html
478
+ * @see middleware https://mongoosejs.com/docs/middleware.html
475
479
  */
476
480
 
477
481
  Model.prototype.save = function(options, fn) {
@@ -702,7 +706,7 @@ Model.prototype.$__delta = function() {
702
706
  where._id = this._doc._id;
703
707
  // If `_id` is an object, need to depopulate, but also need to be careful
704
708
  // because `_id` can technically be null (see gh-6406)
705
- if (get(where, '_id.$__', null) != null) {
709
+ if ((where && where._id && where._id.$__ || null) != null) {
706
710
  where._id = where._id.toObject({ transform: false, depopulate: true });
707
711
  }
708
712
  for (; d < len; ++d) {
@@ -740,7 +744,7 @@ Model.prototype.$__delta = function() {
740
744
  operand(this, where, delta, data, 1, '$unset');
741
745
  } else if (value === null) {
742
746
  operand(this, where, delta, data, null);
743
- } else if (value.isMongooseArray && value.$path() && value[arrayAtomicsSymbol]) {
747
+ } else if (utils.isMongooseArray(value) && value.$path() && value[arrayAtomicsSymbol]) {
744
748
  // arrays and other custom types (support plugins etc)
745
749
  handleAtomics(this, where, delta, data, value);
746
750
  } else if (value[MongooseBuffer.pathSymbol] && Buffer.isBuffer(value)) {
@@ -792,7 +796,7 @@ function checkDivergentArray(doc, path, array) {
792
796
  }
793
797
  }
794
798
 
795
- if (!(pop && array && array.isMongooseArray)) return;
799
+ if (!(pop && utils.isMongooseArray(array))) return;
796
800
 
797
801
  // If the array was populated using options that prevented all
798
802
  // documents from being returned (match, skip, limit) or they
@@ -832,7 +836,8 @@ Model.prototype.$__version = function(where, delta) {
832
836
  if (where === true) {
833
837
  // this is an insert
834
838
  if (key) {
835
- this.$__setValue(key, delta[key] = 0);
839
+ setDottedPath(delta, key, 0);
840
+ this.$__setValue(key, 0);
836
841
  }
837
842
  return;
838
843
  }
@@ -881,7 +886,7 @@ Model.prototype.$__version = function(where, delta) {
881
886
  * doc.save(function (err) { .. })
882
887
  * })
883
888
  *
884
- * @see versionKeys http://mongoosejs.com/docs/guide.html#versionKey
889
+ * @see versionKeys https://mongoosejs.com/docs/guide.html#versionKey
885
890
  * @api public
886
891
  */
887
892
 
@@ -1059,8 +1064,8 @@ Model.prototype.model = function model(name) {
1059
1064
  };
1060
1065
 
1061
1066
  /**
1062
- * Returns true if at least one document exists in the database that matches
1063
- * the given `filter`, and false otherwise.
1067
+ * Returns a document with `_id` only if at least one document exists in the database that matches
1068
+ * the given `filter`, and `null` otherwise.
1064
1069
  *
1065
1070
  * Under the hood, `MyModel.exists({ answer: 42 })` is equivalent to
1066
1071
  * `MyModel.findOne({ answer: 42 }).select({ _id: 1 }).lean()`
@@ -1077,7 +1082,7 @@ Model.prototype.model = function model(name) {
1077
1082
  * - `findOne()`
1078
1083
  *
1079
1084
  * @param {Object} filter
1080
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
1085
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
1081
1086
  * @param {Function} [callback] callback
1082
1087
  * @return {Query}
1083
1088
  */
@@ -1097,10 +1102,6 @@ Model.exists = function exists(filter, options, callback) {
1097
1102
  if (typeof callback === 'function') {
1098
1103
  return query.exec(callback);
1099
1104
  }
1100
- options = options || {};
1101
- if (!options.explain) {
1102
- return query.then(doc => !!doc);
1103
- }
1104
1105
 
1105
1106
  return query;
1106
1107
  };
@@ -1136,11 +1137,13 @@ Model.exists = function exists(filter, options, callback) {
1136
1137
  * @param {Object|String} [options] If string, same as `options.value`.
1137
1138
  * @param {String} [options.value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
1138
1139
  * @param {Boolean} [options.clone=true] By default, `discriminator()` clones the given `schema`. Set to `false` to skip cloning.
1140
+ * @param {Boolean} [options.overwriteModels=false] by default, Mongoose does not allow you to define a discriminator with the same name as another discriminator. Set this to allow overwriting discriminators with the same name.
1139
1141
  * @return {Model} The newly created discriminator model
1140
1142
  * @api public
1141
1143
  */
1142
1144
 
1143
1145
  Model.discriminator = function(name, schema, options) {
1146
+
1144
1147
  let model;
1145
1148
  if (typeof name === 'function') {
1146
1149
  model = name;
@@ -1152,7 +1155,7 @@ Model.discriminator = function(name, schema, options) {
1152
1155
 
1153
1156
  options = options || {};
1154
1157
  const value = utils.isPOJO(options) ? options.value : options;
1155
- const clone = get(options, 'clone', true);
1158
+ const clone = typeof options.clone === 'boolean' ? options.clone : true;
1156
1159
 
1157
1160
  _checkContext(this, 'discriminator');
1158
1161
 
@@ -1164,7 +1167,7 @@ Model.discriminator = function(name, schema, options) {
1164
1167
  }
1165
1168
 
1166
1169
  schema = discriminator(this, name, schema, value, true);
1167
- if (this.db.models[name]) {
1170
+ if (this.db.models[name] && !schema.options.overwriteModels) {
1168
1171
  throw new OverwriteModelError(name);
1169
1172
  }
1170
1173
 
@@ -1226,7 +1229,7 @@ for (const i in EventEmitter.prototype) {
1226
1229
 
1227
1230
  /**
1228
1231
  * This function is responsible for building [indexes](https://docs.mongodb.com/manual/indexes/),
1229
- * unless [`autoIndex`](http://mongoosejs.com/docs/guide.html#autoIndex) is turned off.
1232
+ * unless [`autoIndex`](https://mongoosejs.com/docs/guide.html#autoIndex) is turned off.
1230
1233
  *
1231
1234
  * Mongoose calls this function automatically when a model is created using
1232
1235
  * [`mongoose.model()`](/docs/api.html#mongoose_Mongoose-model) or
@@ -1331,7 +1334,7 @@ Model.init = function init(callback) {
1331
1334
  * });
1332
1335
  *
1333
1336
  * @api public
1334
- * @param {Object} [options] see [MongoDB driver docs](http://mongodb.github.io/node-mongodb-native/3.1/api/Db.html#createCollection)
1337
+ * @param {Object} [options] see [MongoDB driver docs](https://mongodb.github.io/node-mongodb-native/3.1/api/Db.html#createCollection)
1335
1338
  * @param {Function} [callback]
1336
1339
  * @returns {Promise}
1337
1340
  */
@@ -1347,15 +1350,24 @@ Model.createCollection = function createCollection(options, callback) {
1347
1350
  options = void 0;
1348
1351
  }
1349
1352
 
1350
- const schemaCollation = get(this, ['schema', 'options', 'collation'], null);
1353
+ const schemaCollation = this &&
1354
+ this.schema &&
1355
+ this.schema.options &&
1356
+ this.schema.options.collation || null;
1351
1357
  if (schemaCollation != null) {
1352
1358
  options = Object.assign({ collation: schemaCollation }, options);
1353
1359
  }
1354
- const capped = get(this, ['schema', 'options', 'capped']);
1360
+ const capped = this &&
1361
+ this.schema &&
1362
+ this.schema.options &&
1363
+ this.schema.options.capped;
1355
1364
  if (capped) {
1356
1365
  options = Object.assign({ capped: true }, capped, options);
1357
1366
  }
1358
- const timeseries = get(this, ['schema', 'options', 'timeseries']);
1367
+ const timeseries = this &&
1368
+ this.schema &&
1369
+ this.schema.options &&
1370
+ this.schema.options.timeseries;
1359
1371
  if (timeseries != null) {
1360
1372
  options = Object.assign({ timeseries }, options);
1361
1373
  }
@@ -1381,7 +1393,7 @@ Model.createCollection = function createCollection(options, callback) {
1381
1393
  * the model's schema except the `_id` index, and build any indexes that
1382
1394
  * are in your schema but not in MongoDB.
1383
1395
  *
1384
- * See the [introductory blog post](http://thecodebarbarian.com/whats-new-in-mongoose-5-2-syncindexes)
1396
+ * See the [introductory blog post](https://thecodebarbarian.com/whats-new-in-mongoose-5-2-syncindexes)
1385
1397
  * for more information.
1386
1398
  *
1387
1399
  * ####Example:
@@ -1651,7 +1663,7 @@ Model.ensureIndexes = function ensureIndexes(options, callback) {
1651
1663
  };
1652
1664
 
1653
1665
  /**
1654
- * Similar to `ensureIndexes()`, except for it uses the [`createIndex`](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#createIndex)
1666
+ * Similar to `ensureIndexes()`, except for it uses the [`createIndex`](https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#createIndex)
1655
1667
  * function.
1656
1668
  *
1657
1669
  * @param {Object} [options] internal options
@@ -1694,7 +1706,7 @@ function _ensureIndexes(model, options, callback) {
1694
1706
  utils.warn('mongoose: Cannot specify a custom index on `_id` for ' +
1695
1707
  'model name "' + model.modelName + '", ' +
1696
1708
  'MongoDB does not allow overwriting the default `_id` index. See ' +
1697
- 'http://bit.ly/mongodb-id-index');
1709
+ 'https://bit.ly/mongodb-id-index');
1698
1710
  }
1699
1711
  }
1700
1712
 
@@ -2019,7 +2031,7 @@ Model.remove = function remove(conditions, options, callback) {
2019
2031
  * [middleware docs](/docs/middleware.html#naming) to learn more.
2020
2032
  *
2021
2033
  * @param {Object} conditions
2022
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2034
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2023
2035
  * @param {Function} [callback]
2024
2036
  * @return {Query}
2025
2037
  * @api public
@@ -2062,7 +2074,7 @@ Model.deleteOne = function deleteOne(conditions, options, callback) {
2062
2074
  * [middleware docs](/docs/middleware.html#naming) to learn more.
2063
2075
  *
2064
2076
  * @param {Object} conditions
2065
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2077
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2066
2078
  * @param {Function} [callback]
2067
2079
  * @return {Query}
2068
2080
  * @api public
@@ -2113,8 +2125,8 @@ Model.deleteMany = function deleteMany(conditions, options, callback) {
2113
2125
  * await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
2114
2126
  *
2115
2127
  * @param {Object|ObjectId} filter
2116
- * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](http://mongoosejs.com/docs/api.html#query_Query-select)
2117
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2128
+ * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](https://mongoosejs.com/docs/api.html#query_Query-select)
2129
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2118
2130
  * @param {Function} [callback]
2119
2131
  * @return {Query}
2120
2132
  * @see field selection #query_Query-select
@@ -2184,7 +2196,7 @@ Model.find = function find(conditions, projection, options, callback) {
2184
2196
  *
2185
2197
  * @param {Any} id value of `_id` to query by
2186
2198
  * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
2187
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2199
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2188
2200
  * @param {Function} [callback]
2189
2201
  * @return {Query}
2190
2202
  * @see field selection #query_Query-select
@@ -2227,7 +2239,7 @@ Model.findById = function findById(id, projection, options, callback) {
2227
2239
  *
2228
2240
  * @param {Object} [conditions]
2229
2241
  * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
2230
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2242
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2231
2243
  * @param {Function} [callback]
2232
2244
  * @return {Query}
2233
2245
  * @see field selection #query_Query-select
@@ -2481,9 +2493,9 @@ Model.$where = function $where() {
2481
2493
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
2482
2494
  * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
2483
2495
  * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
2484
- * - `setDefaultsOnInsert`: `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
2485
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2486
- * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
2496
+ * - `setDefaultsOnInsert`: `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
2497
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2498
+ * - `strict`: overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict) for this update
2487
2499
  *
2488
2500
  * ####Examples:
2489
2501
  *
@@ -2521,11 +2533,11 @@ Model.$where = function $where() {
2521
2533
  *
2522
2534
  * @param {Object} [conditions]
2523
2535
  * @param {Object} [update]
2524
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2536
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2525
2537
  * @param {String} [options.returnDocument='before'] Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
2526
2538
  * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
2527
2539
  * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
2528
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
2540
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
2529
2541
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
2530
2542
  * @param {Boolean} [options.overwrite=false] By default, if you don't include any [update operators](https://docs.mongodb.com/manual/reference/operator/update/) in `update`, Mongoose will wrap `update` in `$set` for you. This prevents you from accidentally overwriting the document. This option tells Mongoose to skip adding `$set`. An alternative to this would be using [Model.findOneAndReplace(conditions, update, options, callback)](https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndReplace).
2531
2543
  * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
@@ -2533,7 +2545,7 @@ Model.$where = function $where() {
2533
2545
  * @param {Function} [callback]
2534
2546
  * @return {Query}
2535
2547
  * @see Tutorial /docs/tutorials/findoneandupdate.html
2536
- * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
2548
+ * @see mongodb https://www.mongodb.org/display/DOCS/findAndModify+Command
2537
2549
  * @api public
2538
2550
  */
2539
2551
 
@@ -2581,7 +2593,7 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) {
2581
2593
  */
2582
2594
 
2583
2595
  function _decorateUpdateWithVersionKey(update, options, versionKey) {
2584
- if (!versionKey || !get(options, 'upsert', false)) {
2596
+ if (!versionKey || !(options && options.upsert || false)) {
2585
2597
  return;
2586
2598
  }
2587
2599
 
@@ -2615,11 +2627,11 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
2615
2627
  * - `new`: bool - true to return the modified document rather than the original. defaults to false
2616
2628
  * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
2617
2629
  * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
2618
- * - `setDefaultsOnInsert`: `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
2630
+ * - `setDefaultsOnInsert`: `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
2619
2631
  * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
2620
2632
  * - `select`: sets the document fields to return
2621
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2622
- * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
2633
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2634
+ * - `strict`: overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict) for this update
2623
2635
  *
2624
2636
  * ####Examples:
2625
2637
  *
@@ -2658,17 +2670,17 @@ function _decorateUpdateWithVersionKey(update, options, versionKey) {
2658
2670
  *
2659
2671
  * @param {Object|Number|String} id value of `_id` to query by
2660
2672
  * @param {Object} [update]
2661
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2673
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2662
2674
  * @param {String} [options.returnDocument='before'] Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
2663
2675
  * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
2664
2676
  * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
2665
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
2677
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
2666
2678
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
2667
2679
  * @param {Boolean} [options.overwrite=false] By default, if you don't include any [update operators](https://docs.mongodb.com/manual/reference/operator/update/) in `update`, Mongoose will wrap `update` in `$set` for you. This prevents you from accidentally overwriting the document. This option tells Mongoose to skip adding `$set`. An alternative to this would be using [Model.findOneAndReplace({ _id: id }, update, options, callback)](https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndReplace).
2668
2680
  * @param {Function} [callback]
2669
2681
  * @return {Query}
2670
2682
  * @see Model.findOneAndUpdate #model_Model.findOneAndUpdate
2671
- * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
2683
+ * @see mongodb https://www.mongodb.org/display/DOCS/findAndModify+Command
2672
2684
  * @api public
2673
2685
  */
2674
2686
 
@@ -2719,8 +2731,8 @@ Model.findByIdAndUpdate = function(id, update, options, callback) {
2719
2731
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
2720
2732
  * - `select`: sets the document fields to return, ex. `{ projection: { _id: 0 } }`
2721
2733
  * - `projection`: equivalent to `select`
2722
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2723
- * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
2734
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2735
+ * - `strict`: overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict) for this update
2724
2736
  *
2725
2737
  * ####Examples:
2726
2738
  *
@@ -2743,8 +2755,8 @@ Model.findByIdAndUpdate = function(id, update, options, callback) {
2743
2755
  * });
2744
2756
  *
2745
2757
  * @param {Object} conditions
2746
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2747
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
2758
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2759
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
2748
2760
  * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
2749
2761
  * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
2750
2762
  * @param {Function} [callback]
@@ -2791,12 +2803,12 @@ Model.findOneAndDelete = function(conditions, options, callback) {
2791
2803
  * - `findOneAndDelete()`
2792
2804
  *
2793
2805
  * @param {Object|Number|String} id value of `_id` to query by
2794
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2795
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
2806
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2807
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
2796
2808
  * @param {Function} [callback]
2797
2809
  * @return {Query}
2798
2810
  * @see Model.findOneAndRemove #model_Model.findOneAndRemove
2799
- * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
2811
+ * @see mongodb https://www.mongodb.org/display/DOCS/findAndModify+Command
2800
2812
  */
2801
2813
 
2802
2814
  Model.findByIdAndDelete = function(id, options, callback) {
@@ -2832,8 +2844,8 @@ Model.findByIdAndDelete = function(id, options, callback) {
2832
2844
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
2833
2845
  * - `select`: sets the document fields to return
2834
2846
  * - `projection`: like select, it determines which fields to return, ex. `{ projection: { _id: 0 } }`
2835
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2836
- * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
2847
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2848
+ * - `strict`: overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict) for this update
2837
2849
  *
2838
2850
  * ####Examples:
2839
2851
  *
@@ -2845,11 +2857,11 @@ Model.findByIdAndDelete = function(id, options, callback) {
2845
2857
  *
2846
2858
  * @param {Object} filter Replace the first document that matches this filter
2847
2859
  * @param {Object} [replacement] Replace with this document
2848
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2860
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2849
2861
  * @param {String} [options.returnDocument='before'] Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
2850
2862
  * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
2851
2863
  * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
2852
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
2864
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
2853
2865
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
2854
2866
  * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
2855
2867
  * @param {Function} [callback]
@@ -2909,8 +2921,8 @@ Model.findOneAndReplace = function(filter, replacement, options, callback) {
2909
2921
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
2910
2922
  * - `select`: sets the document fields to return
2911
2923
  * - `projection`: like select, it determines which fields to return, ex. `{ projection: { _id: 0 } }`
2912
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2913
- * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
2924
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2925
+ * - `strict`: overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict) for this update
2914
2926
  *
2915
2927
  * ####Examples:
2916
2928
  *
@@ -2933,13 +2945,13 @@ Model.findOneAndReplace = function(filter, replacement, options, callback) {
2933
2945
  * });
2934
2946
  *
2935
2947
  * @param {Object} conditions
2936
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
2948
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
2937
2949
  * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
2938
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
2950
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
2939
2951
  * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
2940
2952
  * @param {Function} [callback]
2941
2953
  * @return {Query}
2942
- * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
2954
+ * @see mongodb https://www.mongodb.org/display/DOCS/findAndModify+Command
2943
2955
  * @api public
2944
2956
  */
2945
2957
 
@@ -2987,8 +2999,8 @@ Model.findOneAndRemove = function(conditions, options, callback) {
2987
2999
  *
2988
3000
  * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
2989
3001
  * - `select`: sets the document fields to return
2990
- * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
2991
- * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
3002
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
3003
+ * - `strict`: overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict) for this update
2992
3004
  *
2993
3005
  * ####Examples:
2994
3006
  *
@@ -2999,14 +3011,14 @@ Model.findOneAndRemove = function(conditions, options, callback) {
2999
3011
  * A.findByIdAndRemove() // returns Query
3000
3012
  *
3001
3013
  * @param {Object|Number|String} id value of `_id` to query by
3002
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
3003
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
3014
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
3015
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
3004
3016
  * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
3005
3017
  * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
3006
3018
  * @param {Function} [callback]
3007
3019
  * @return {Query}
3008
3020
  * @see Model.findOneAndRemove #model_Model.findOneAndRemove
3009
- * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
3021
+ * @see mongodb https://www.mongodb.org/display/DOCS/findAndModify+Command
3010
3022
  */
3011
3023
 
3012
3024
  Model.findByIdAndRemove = function(id, options, callback) {
@@ -3151,7 +3163,7 @@ Model.create = function create(doc, options, callback) {
3151
3163
  return cb(firstError, savedDocs);
3152
3164
  }
3153
3165
 
3154
- if (doc instanceof Array) {
3166
+ if (Array.isArray(doc)) {
3155
3167
  cb(null, savedDocs);
3156
3168
  } else {
3157
3169
  cb.apply(this, [null].concat(savedDocs));
@@ -3197,7 +3209,7 @@ Model.create = function create(doc, options, callback) {
3197
3209
  * await doc.remove();
3198
3210
  *
3199
3211
  * @param {Array} [pipeline]
3200
- * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#watch)
3212
+ * @param {Object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#watch)
3201
3213
  * @return {ChangeStream} mongoose-specific change stream wrapper, inherits from EventEmitter
3202
3214
  * @api public
3203
3215
  */
@@ -3228,7 +3240,7 @@ Model.watch = function(pipeline, options) {
3228
3240
  /**
3229
3241
  * _Requires MongoDB >= 3.6.0._ Starts a [MongoDB session](https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions)
3230
3242
  * for benefits like causal consistency, [retryable writes](https://docs.mongodb.com/manual/core/retryable-writes/),
3231
- * and [transactions](http://thecodebarbarian.com/a-node-js-perspective-on-mongodb-4-transactions.html).
3243
+ * and [transactions](https://thecodebarbarian.com/a-node-js-perspective-on-mongodb-4-transactions.html).
3232
3244
  *
3233
3245
  * Calling `MyModel.startSession()` is equivalent to calling `MyModel.db.startSession()`.
3234
3246
  *
@@ -3245,7 +3257,7 @@ Model.watch = function(pipeline, options) {
3245
3257
  * // secondary that is experiencing replication lag.
3246
3258
  * doc = await Person.findOne({ name: 'Ned Stark' }, null, { session, readPreference: 'secondary' });
3247
3259
  *
3248
- * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html#startSession)
3260
+ * @param {Object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html#startSession)
3249
3261
  * @param {Boolean} [options.causalConsistency=true] set to false to disable causal consistency
3250
3262
  * @param {Function} [callback]
3251
3263
  * @return {Promise<ClientSession>} promise that resolves to a MongoDB driver `ClientSession`
@@ -3281,9 +3293,9 @@ Model.startSession = function() {
3281
3293
  * Movies.insertMany(arr, function(error, docs) {});
3282
3294
  *
3283
3295
  * @param {Array|Object|*} doc(s)
3284
- * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insertMany)
3296
+ * @param {Object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insertMany)
3285
3297
  * @param {Boolean} [options.ordered = true] if true, will fail fast on the first error encountered. If false, will insert all the documents it can and report errors later. An `insertMany()` with `ordered = false` is called an "unordered" `insertMany()`.
3286
- * @param {Boolean} [options.rawResult = false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `true`, will return the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~insertWriteOpCallback) with a `mongoose` property that contains `validationErrors` if this is an unordered `insertMany`.
3298
+ * @param {Boolean} [options.rawResult = false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `true`, will return the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~insertWriteOpCallback) with a `mongoose` property that contains `validationErrors` if this is an unordered `insertMany`.
3287
3299
  * @param {Boolean} [options.lean = false] if `true`, skips hydrating and validating the documents. This option is useful if you need the extra performance, but Mongoose won't validate the documents before inserting.
3288
3300
  * @param {Number} [options.limit = null] this limits the number of documents being processed (validation/casting) by mongoose in parallel, this does **NOT** send the documents in batches to MongoDB. Use this option if you're processing a large number of documents and your app is running out of memory.
3289
3301
  * @param {String|Object|Array} [options.populate = null] populates the result documents. This option is a no-op if `rawResult` is set.
@@ -3320,10 +3332,10 @@ Model.$__insertMany = function(arr, options, callback) {
3320
3332
  }
3321
3333
  callback = callback || utils.noop;
3322
3334
  options = options || {};
3323
- const limit = get(options, 'limit', 1000);
3324
- const rawResult = get(options, 'rawResult', false);
3325
- const ordered = get(options, 'ordered', true);
3326
- const lean = get(options, 'lean', false);
3335
+ const limit = options.limit || 1000;
3336
+ const rawResult = !!options.rawResult;
3337
+ const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
3338
+ const lean = !!options.lean;
3327
3339
 
3328
3340
  if (!Array.isArray(arr)) {
3329
3341
  arr = [arr];
@@ -3374,7 +3386,7 @@ Model.$__insertMany = function(arr, options, callback) {
3374
3386
  return doc != null;
3375
3387
  });
3376
3388
  // Quickly escape while there aren't any valid docAttributes
3377
- if (docAttributes.length < 1) {
3389
+ if (docAttributes.length === 0) {
3378
3390
  if (rawResult) {
3379
3391
  const res = {
3380
3392
  mongoose: {
@@ -3401,12 +3413,12 @@ Model.$__insertMany = function(arr, options, callback) {
3401
3413
  // `writeErrors` is a property reported by the MongoDB driver,
3402
3414
  // just not if there's only 1 error.
3403
3415
  if (error.writeErrors == null &&
3404
- get(error, 'result.result.writeErrors') != null) {
3416
+ (error.result && error.result.result && error.result.result.writeErrors) != null) {
3405
3417
  error.writeErrors = error.result.result.writeErrors;
3406
3418
  }
3407
3419
 
3408
3420
  // `insertedDocs` is a Mongoose-specific property
3409
- const erroredIndexes = new Set(get(error, 'writeErrors', []).map(err => err.index));
3421
+ const erroredIndexes = new Set((error && error.writeErrors || []).map(err => err.index));
3410
3422
 
3411
3423
  let firstErroredIndex = -1;
3412
3424
  error.insertedDocs = docAttributes.
@@ -3493,7 +3505,7 @@ function _setIsNew(doc, val) {
3493
3505
  *
3494
3506
  * This function does **not** trigger any middleware, neither `save()`, nor `update()`.
3495
3507
  * If you need to trigger
3496
- * `save()` middleware for every document use [`create()`](http://mongoosejs.com/docs/api.html#model_Model.create) instead.
3508
+ * `save()` middleware for every document use [`create()`](https://mongoosejs.com/docs/api.html#model_Model.create) instead.
3497
3509
  *
3498
3510
  * ####Example:
3499
3511
  *
@@ -3564,7 +3576,7 @@ function _setIsNew(doc, val) {
3564
3576
  * @param {Boolean} [options.bypassDocumentValidation=false] If true, disable [MongoDB server-side schema validation](https://docs.mongodb.com/manual/core/schema-validation/) for all writes in this bulk.
3565
3577
  * @param {Boolean} [options.strict=null] Overwrites the [`strict` option](/docs/guide.html#strict) on schema. If false, allows filtering and writing fields not defined in the schema for all writes in this bulk.
3566
3578
  * @param {Function} [callback] callback `function(error, bulkWriteOpResult) {}`
3567
- * @return {Promise} resolves to a [`BulkWriteOpResult`](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~BulkWriteOpResult) if the operation succeeds
3579
+ * @return {Promise} resolves to a [`BulkWriteOpResult`](https://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~BulkWriteOpResult) if the operation succeeds
3568
3580
  * @api public
3569
3581
  */
3570
3582
 
@@ -3609,20 +3621,25 @@ Model.bulkWrite = function(ops, options, callback) {
3609
3621
  * `bulkSave` uses `bulkWrite` under the hood, so it's mostly useful when dealing with many documents (10K+)
3610
3622
  *
3611
3623
  * @param {[Document]} documents
3624
+ * @param {Object} [options] options passed to the underlying `bulkWrite()`
3625
+ * @param {ClientSession} [options.session=null] The session associated with this bulk write. See [transactions docs](/docs/transactions.html).
3626
+ * @param {String|number} [options.w=1] The [write concern](https://docs.mongodb.com/manual/reference/write-concern/). See [`Query#w()`](/docs/api.html#query_Query-w) for more information.
3627
+ * @param {number} [options.wtimeout=null] The [write concern timeout](https://docs.mongodb.com/manual/reference/write-concern/#wtimeout).
3628
+ * @param {Boolean} [options.j=true] If false, disable [journal acknowledgement](https://docs.mongodb.com/manual/reference/write-concern/#j-option)
3612
3629
  *
3613
3630
  */
3614
- Model.bulkSave = function(documents) {
3631
+ Model.bulkSave = function(documents, options) {
3615
3632
  const preSavePromises = documents.map(buildPreSavePromise);
3616
3633
 
3617
3634
  const writeOperations = this.buildBulkWriteOperations(documents, { skipValidation: true });
3618
3635
 
3619
3636
  let bulkWriteResultPromise;
3620
3637
  return Promise.all(preSavePromises)
3621
- .then(() => bulkWriteResultPromise = this.bulkWrite(writeOperations))
3638
+ .then(() => bulkWriteResultPromise = this.bulkWrite(writeOperations, options))
3622
3639
  .then(() => documents.map(buildSuccessfulWriteHandlerPromise))
3623
3640
  .then(() => bulkWriteResultPromise)
3624
3641
  .catch((err) => {
3625
- if (!get(err, 'writeErrors.length')) {
3642
+ if (!(err && err.writeErrors && err.writeErrors.length)) {
3626
3643
  throw err;
3627
3644
  }
3628
3645
  return Promise.all(
@@ -3762,6 +3779,13 @@ Model.buildBulkWriteOperations = function buildBulkWriteOperations(documents, op
3762
3779
  Model.hydrate = function(obj, projection) {
3763
3780
  _checkContext(this, 'hydrate');
3764
3781
 
3782
+ if (projection != null) {
3783
+ if (obj != null && obj.$__ != null) {
3784
+ obj = obj.toObject(internalToObjectOptions);
3785
+ }
3786
+ obj = applyProjection(obj, projection);
3787
+ }
3788
+
3765
3789
  const document = require('./queryhelpers').createModel(this, obj, projection);
3766
3790
  document.$init(obj);
3767
3791
  return document;
@@ -3793,7 +3817,7 @@ Model.hydrate = function(obj, projection) {
3793
3817
  * - `writeConcern` (object): sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
3794
3818
  * - `multi` (boolean): whether multiple documents should be updated (false)
3795
3819
  * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
3796
- * - `setDefaultsOnInsert` (boolean): if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
3820
+ * - `setDefaultsOnInsert` (boolean): if this and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
3797
3821
  * - `timestamps` (boolean): If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
3798
3822
  * - `overwrite` (boolean): disables update-only mode, allowing you to overwrite the doc (false)
3799
3823
  *
@@ -3824,8 +3848,8 @@ Model.hydrate = function(obj, projection) {
3824
3848
  * Be careful to not use an existing model instance for the update clause (this won't work and can cause weird behavior like infinite loops). Also, ensure that the update clause does not have an _id property, which causes Mongo to return a "Mod on _id not allowed" error.
3825
3849
  *
3826
3850
  * @deprecated
3827
- * @see strict http://mongoosejs.com/docs/guide.html#strict
3828
- * @see response http://docs.mongodb.org/v2.6/reference/command/update/#output
3851
+ * @see strict https://mongoosejs.com/docs/guide.html#strict
3852
+ * @see response https://docs.mongodb.org/v2.6/reference/command/update/#output
3829
3853
  * @param {Object} filter
3830
3854
  * @param {Object} doc
3831
3855
  * @param {Object} [options] optional see [`Query.prototype.setOptions()`](/docs/api.html#query_Query-setOptions)
@@ -3834,7 +3858,7 @@ Model.hydrate = function(obj, projection) {
3834
3858
  * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
3835
3859
  * @param {Boolean} [options.multi=false] whether multiple documents should be updated or just the first one that matches `filter`.
3836
3860
  * @param {Boolean} [options.runValidators=false] if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
3837
- * @param {Boolean} [options.setDefaultsOnInsert=false] `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
3861
+ * @param {Boolean} [options.setDefaultsOnInsert=false] `true` by default. If `setDefaultsOnInsert` and `upsert` are true, mongoose will apply the [defaults](https://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created.
3838
3862
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
3839
3863
  * @param {Boolean} [options.overwrite=false] By default, if you don't include any [update operators](https://docs.mongodb.com/manual/reference/operator/update/) in `doc`, Mongoose will wrap `doc` in `$set` for you. This prevents you from accidentally overwriting the document. This option tells Mongoose to skip adding `$set`.
3840
3864
  * @param {Function} [callback] params are (error, [updateWriteOpResult](https://mongodb.github.io/node-mongodb-native/3.6/api/Collection.html#~updateWriteOpResult))
@@ -3874,8 +3898,8 @@ Model.update = function update(conditions, doc, options, callback) {
3874
3898
  *
3875
3899
  * @param {Object} filter
3876
3900
  * @param {Object|Array} update
3877
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
3878
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
3901
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
3902
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
3879
3903
  * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
3880
3904
  * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
3881
3905
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
@@ -3883,7 +3907,7 @@ Model.update = function update(conditions, doc, options, callback) {
3883
3907
  * @return {Query}
3884
3908
  * @see Query docs https://mongoosejs.com/docs/queries.html
3885
3909
  * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
3886
- * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
3910
+ * @see writeOpResult https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
3887
3911
  * @api public
3888
3912
  */
3889
3913
 
@@ -3914,8 +3938,8 @@ Model.updateMany = function updateMany(conditions, doc, options, callback) {
3914
3938
  *
3915
3939
  * @param {Object} filter
3916
3940
  * @param {Object|Array} update
3917
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
3918
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
3941
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
3942
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
3919
3943
  * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
3920
3944
  * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
3921
3945
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
@@ -3923,7 +3947,7 @@ Model.updateMany = function updateMany(conditions, doc, options, callback) {
3923
3947
  * @return {Query}
3924
3948
  * @see Query docs https://mongoosejs.com/docs/queries.html
3925
3949
  * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
3926
- * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
3950
+ * @see writeOpResult https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
3927
3951
  * @api public
3928
3952
  */
3929
3953
 
@@ -3951,15 +3975,15 @@ Model.updateOne = function updateOne(conditions, doc, options, callback) {
3951
3975
  *
3952
3976
  * @param {Object} filter
3953
3977
  * @param {Object} doc
3954
- * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
3955
- * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
3978
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](https://mongoosejs.com/docs/api.html#query_Query-setOptions)
3979
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](https://mongoosejs.com/docs/guide.html#strict)
3956
3980
  * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
3957
3981
  * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
3958
3982
  * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
3959
3983
  * @param {Function} [callback] `function(error, res) {}` where `res` has 3 properties: `n`, `nModified`, `ok`.
3960
3984
  * @return {Query}
3961
3985
  * @see Query docs https://mongoosejs.com/docs/queries.html
3962
- * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
3986
+ * @see writeOpResult https://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
3963
3987
  * @return {Query}
3964
3988
  * @api public
3965
3989
  */
@@ -3967,7 +3991,7 @@ Model.updateOne = function updateOne(conditions, doc, options, callback) {
3967
3991
  Model.replaceOne = function replaceOne(conditions, doc, options, callback) {
3968
3992
  _checkContext(this, 'replaceOne');
3969
3993
 
3970
- const versionKey = get(this, 'schema.options.versionKey', null);
3994
+ const versionKey = this && this.schema && this.schema.options && this.schema.options.versionKey || null;
3971
3995
  if (versionKey && !doc[versionKey]) {
3972
3996
  doc[versionKey] = 0;
3973
3997
  }
@@ -3992,7 +4016,10 @@ function _update(model, op, conditions, doc, options, callback) {
3992
4016
  }
3993
4017
  options = typeof options === 'function' ? options : utils.clone(options);
3994
4018
 
3995
- const versionKey = get(model, 'schema.options.versionKey', null);
4019
+ const versionKey = model &&
4020
+ model.schema &&
4021
+ model.schema.options &&
4022
+ model.schema.options.versionKey || null;
3996
4023
  _decorateUpdateWithVersionKey(doc, options, versionKey);
3997
4024
 
3998
4025
  return mq[op](conditions, doc, options, callback);
@@ -4001,7 +4028,7 @@ function _update(model, op, conditions, doc, options, callback) {
4001
4028
  /**
4002
4029
  * Executes a mapReduce command.
4003
4030
  *
4004
- * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. See [node-mongodb-native mapReduce() documentation](http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#mapreduce) for more detail about options.
4031
+ * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. See [node-mongodb-native mapReduce() documentation](https://mongodb.github.io/node-mongodb-native/api-generated/collection.html#mapreduce) for more detail about options.
4005
4032
  *
4006
4033
  * This function does not trigger any middleware.
4007
4034
  *
@@ -4070,7 +4097,7 @@ function _update(model, op, conditions, doc, options, callback) {
4070
4097
  *
4071
4098
  * @param {Object} o an object specifying map-reduce options
4072
4099
  * @param {Function} [callback] optional callback
4073
- * @see http://www.mongodb.org/display/DOCS/MapReduce
4100
+ * @see https://www.mongodb.org/display/DOCS/MapReduce
4074
4101
  * @return {Promise}
4075
4102
  * @api public
4076
4103
  */
@@ -4123,7 +4150,7 @@ Model.mapReduce = function mapReduce(o, callback) {
4123
4150
  };
4124
4151
 
4125
4152
  /**
4126
- * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection.
4153
+ * Performs [aggregations](https://docs.mongodb.org/manual/applications/aggregation/) on the models collection.
4127
4154
  *
4128
4155
  * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned.
4129
4156
  *
@@ -4157,10 +4184,10 @@ Model.mapReduce = function mapReduce(o, callback) {
4157
4184
  *
4158
4185
  * - [Mongoose `Aggregate`](/docs/api/aggregate.html)
4159
4186
  * - [An Introduction to Mongoose Aggregate](https://masteringjs.io/tutorials/mongoose/aggregate)
4160
- * - [MongoDB Aggregation docs](http://docs.mongodb.org/manual/applications/aggregation/)
4187
+ * - [MongoDB Aggregation docs](https://docs.mongodb.org/manual/applications/aggregation/)
4161
4188
  *
4162
4189
  * @see Aggregate #aggregate_Aggregate
4163
- * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
4190
+ * @see MongoDB https://docs.mongodb.org/manual/applications/aggregation/
4164
4191
  * @param {Array} [pipeline] aggregation pipeline as an array of objects
4165
4192
  * @param {Object} [options] aggregation options
4166
4193
  * @param {Function} [callback]
@@ -4171,7 +4198,7 @@ Model.mapReduce = function mapReduce(o, callback) {
4171
4198
  Model.aggregate = function aggregate(pipeline, options, callback) {
4172
4199
  _checkContext(this, 'aggregate');
4173
4200
 
4174
- if (arguments.length > 3 || get(pipeline, 'constructor.name') === 'Object') {
4201
+ if (arguments.length > 3 || (pipeline && pipeline.constructor && pipeline.constructor.name) === 'Object') {
4175
4202
  throw new MongooseError('Mongoose 5.x disallows passing a spread of operators ' +
4176
4203
  'to `Model.aggregate()`. Instead of ' +
4177
4204
  '`Model.aggregate({ $match }, { $skip })`, do ' +
@@ -4451,9 +4478,16 @@ const excludeIdRegGlobal = /\s?-_id\s?/g;
4451
4478
 
4452
4479
  function populate(model, docs, options, callback) {
4453
4480
  const populateOptions = { ...options };
4454
- if (model.base.options.strictPopulate != null && options.strictPopulate == null) {
4455
- populateOptions.strictPopulate = model.base.options.strictPopulate;
4481
+ if (options.strictPopulate == null) {
4482
+ if (options._localModel != null && options._localModel.schema._userProvidedOptions.strictPopulate != null) {
4483
+ populateOptions.strictPopulate = options._localModel.schema._userProvidedOptions.strictPopulate;
4484
+ } else if (options._localModel != null && model.base.options.strictPopulate != null) {
4485
+ populateOptions.strictPopulate = model.base.options.strictPopulate;
4486
+ } else if (model.base.options.strictPopulate != null) {
4487
+ populateOptions.strictPopulate = model.base.options.strictPopulate;
4488
+ }
4456
4489
  }
4490
+
4457
4491
  // normalize single / multiple docs passed
4458
4492
  if (!Array.isArray(docs)) {
4459
4493
  docs = [docs];
@@ -4487,7 +4521,10 @@ function populate(model, docs, options, callback) {
4487
4521
  ids = utils.array.unique(ids);
4488
4522
 
4489
4523
  const assignmentOpts = {};
4490
- assignmentOpts.sort = get(mod, 'options.options.sort', void 0);
4524
+ assignmentOpts.sort = mod &&
4525
+ mod.options &&
4526
+ mod.options.options &&
4527
+ mod.options.options.sort || void 0;
4491
4528
  assignmentOpts.excludeId = excludeIdReg.test(select) || (select && select._id === 0);
4492
4529
 
4493
4530
  if (ids.length === 0 || ids.every(utils.isNullOrUndefined)) {
@@ -4524,7 +4561,7 @@ function populate(model, docs, options, callback) {
4524
4561
  }
4525
4562
  if (!hasOne) {
4526
4563
  // If models but no docs, skip further deep populate.
4527
- if (modelsMap.length > 0) {
4564
+ if (modelsMap.length !== 0) {
4528
4565
  return callback();
4529
4566
  }
4530
4567
  // If no models to populate but we have a nested populate,
@@ -4656,7 +4693,9 @@ function _assign(model, vals, mod, assignmentOpts) {
4656
4693
  const isVirtual = mod.isVirtual;
4657
4694
  const justOne = mod.justOne;
4658
4695
  let _val;
4659
- const lean = get(options, 'options.lean', false);
4696
+ const lean = options &&
4697
+ options.options &&
4698
+ options.options.lean || false;
4660
4699
  const len = vals.length;
4661
4700
  const rawOrder = {};
4662
4701
  const rawDocs = {};