mongoose 6.2.9 → 6.3.0

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 (64) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/browser.umd.js +2 -1693
  3. package/lib/aggregate.js +59 -67
  4. package/lib/browser.js +4 -4
  5. package/lib/connection.js +21 -21
  6. package/lib/cursor/AggregationCursor.js +2 -2
  7. package/lib/cursor/ChangeStream.js +42 -2
  8. package/lib/cursor/QueryCursor.js +5 -3
  9. package/lib/document.js +39 -46
  10. package/lib/error/eachAsyncMultiError.js +41 -0
  11. package/lib/error/index.js +2 -2
  12. package/lib/helpers/cursor/eachAsync.js +44 -12
  13. package/lib/helpers/indexes/applySchemaCollation.js +13 -0
  14. package/lib/helpers/indexes/isTextIndex.js +16 -0
  15. package/lib/helpers/model/discriminator.js +1 -3
  16. package/lib/helpers/populate/markArraySubdocsPopulated.js +1 -1
  17. package/lib/helpers/projection/hasIncludedChildren.js +1 -1
  18. package/lib/helpers/query/applyGlobalOption.js +29 -0
  19. package/lib/helpers/query/castUpdate.js +3 -1
  20. package/lib/helpers/update/applyTimestampsToChildren.js +2 -2
  21. package/lib/helpers/update/applyTimestampsToUpdate.js +0 -1
  22. package/lib/index.js +33 -26
  23. package/lib/model.js +88 -90
  24. package/lib/options/SchemaArrayOptions.js +2 -2
  25. package/lib/options/SchemaBufferOptions.js +1 -1
  26. package/lib/options/SchemaDateOptions.js +2 -2
  27. package/lib/options/SchemaDocumentArrayOptions.js +3 -3
  28. package/lib/options/SchemaMapOptions.js +2 -2
  29. package/lib/options/SchemaNumberOptions.js +3 -3
  30. package/lib/options/SchemaObjectIdOptions.js +2 -2
  31. package/lib/options/SchemaStringOptions.js +1 -1
  32. package/lib/options/SchemaSubdocumentOptions.js +2 -2
  33. package/lib/options/SchemaTypeOptions.js +3 -3
  34. package/lib/query.js +273 -249
  35. package/lib/schema/SubdocumentPath.js +4 -3
  36. package/lib/schema/array.js +2 -2
  37. package/lib/schema/boolean.js +4 -4
  38. package/lib/schema/buffer.js +3 -3
  39. package/lib/schema/date.js +7 -7
  40. package/lib/schema/decimal128.js +2 -2
  41. package/lib/schema/documentarray.js +3 -3
  42. package/lib/schema/mixed.js +2 -2
  43. package/lib/schema/number.js +6 -6
  44. package/lib/schema/objectid.js +4 -7
  45. package/lib/schema/string.js +38 -16
  46. package/lib/schema.js +144 -30
  47. package/lib/schematype.js +75 -68
  48. package/lib/types/ArraySubdocument.js +1 -1
  49. package/lib/types/DocumentArray/methods/index.js +2 -2
  50. package/lib/types/array/index.js +1 -1
  51. package/lib/types/array/methods/index.js +13 -13
  52. package/lib/types/buffer.js +1 -1
  53. package/lib/types/decimal128.js +1 -1
  54. package/lib/types/objectid.js +1 -1
  55. package/lib/types/subdocument.js +31 -2
  56. package/lib/validoptions.js +1 -0
  57. package/lib/virtualtype.js +3 -3
  58. package/package.json +19 -13
  59. package/tools/repl.js +2 -1
  60. package/types/aggregate.d.ts +223 -0
  61. package/types/cursor.d.ts +10 -4
  62. package/types/index.d.ts +194 -209
  63. package/types/mongooseoptions.d.ts +10 -4
  64. package/lib/helpers/query/applyGlobalMaxTimeMS.js +0 -15
package/lib/query.js CHANGED
@@ -11,7 +11,8 @@ const MongooseError = require('./error/mongooseError');
11
11
  const ObjectParameterError = require('./error/objectParameter');
12
12
  const QueryCursor = require('./cursor/QueryCursor');
13
13
  const ReadPreference = require('./driver').get().ReadPreference;
14
- const applyGlobalMaxTimeMS = require('./helpers/query/applyGlobalMaxTimeMS');
14
+ const ValidationError = require('./error/validation');
15
+ const { applyGlobalMaxTimeMS, applyGlobalDiskUse } = require('./helpers/query/applyGlobalOption');
15
16
  const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
16
17
  const cast = require('./cast');
17
18
  const castArrayFilters = require('./helpers/update/castArrayFilters');
@@ -69,7 +70,7 @@ const queryOptionMethods = new Set([
69
70
  * to instantiate a `Query` directly. Instead use Model functions like
70
71
  * [`Model.find()`](/docs/api.html#find_find).
71
72
  *
72
- * ####Example:
73
+ * #### Example:
73
74
  *
74
75
  * const query = MyModel.find(); // `query` is an instance of `Query`
75
76
  * query.setOptions({ lean : true });
@@ -154,7 +155,9 @@ Query.base = mquery.prototype;
154
155
  /**
155
156
  * Flag to opt out of using `$geoWithin`.
156
157
  *
157
- * mongoose.Query.use$geoWithin = false;
158
+ * ```javascript
159
+ * mongoose.Query.use$geoWithin = false;
160
+ * ```
158
161
  *
159
162
  * MongoDB 2.4 deprecated the use of `$within`, replacing it with `$geoWithin`. Mongoose uses `$geoWithin` by default (which is 100% backward compatible with `$within`). If you are running an older version of MongoDB, set this flag to `false` so your `within()` queries continue to work.
160
163
  *
@@ -171,7 +174,7 @@ Query.use$geoWithin = mquery.use$geoWithin;
171
174
  /**
172
175
  * Converts this query to a customized, reusable query constructor with all arguments and options retained.
173
176
  *
174
- * ####Example
177
+ * #### Example
175
178
  *
176
179
  * // Create a query for adventure movies and read from the primary
177
180
  * // node in the replica-set unless it is down, in which case we'll
@@ -253,7 +256,7 @@ Query.prototype.toConstructor = function toConstructor() {
253
256
  /**
254
257
  * Make a copy of this query so you can re-execute it.
255
258
  *
256
- * ####Example:
259
+ * #### Example:
257
260
  * const q = Book.findOne({ title: 'Casino Royale' });
258
261
  * await q.exec();
259
262
  * await q.exec(); // Throws an error because you can't execute a query twice
@@ -301,7 +304,7 @@ Query.prototype.clone = function clone() {
301
304
  /**
302
305
  * Specifies a javascript function or expression to pass to MongoDBs query system.
303
306
  *
304
- * ####Example
307
+ * #### Example
305
308
  *
306
309
  * query.$where('this.comments.length === 10 || this.name.length === 5')
307
310
  *
@@ -311,7 +314,7 @@ Query.prototype.clone = function clone() {
311
314
  * return this.comments.length === 10 || this.name.length === 5;
312
315
  * })
313
316
  *
314
- * ####NOTE:
317
+ * #### Note:
315
318
  *
316
319
  * Only use `$where` when you have a condition that cannot be met using other MongoDB operators like `$lt`.
317
320
  * **Be sure to read about all of [its caveats](https://docs.mongodb.org/manual/reference/operator/where/) before using.**
@@ -329,7 +332,7 @@ Query.prototype.clone = function clone() {
329
332
  /**
330
333
  * Specifies a `path` for use with chaining.
331
334
  *
332
- * ####Example
335
+ * #### Example
333
336
  *
334
337
  * // instead of writing:
335
338
  * User.find({age: {$gte: 21, $lte: 65}}, callback);
@@ -359,13 +362,13 @@ Query.prototype.clone = function clone() {
359
362
  /**
360
363
  * Specifies a `$slice` projection for an array.
361
364
  *
362
- * ####Example
365
+ * #### Example
363
366
  *
364
- * query.slice('comments', 5)
365
- * query.slice('comments', -5)
366
- * query.slice('comments', [10, 5])
367
- * query.where('comments').slice(5)
368
- * query.where('comments').slice([-10, 5])
367
+ * query.slice('comments', 5);
368
+ * query.slice('comments', -5);
369
+ * query.slice('comments', [10, 5]);
370
+ * query.where('comments').slice(5);
371
+ * query.where('comments').slice([-10, 5]);
369
372
  *
370
373
  * @method slice
371
374
  * @memberOf Query
@@ -437,7 +440,7 @@ Query.prototype._validateOp = function() {
437
440
  /**
438
441
  * Specifies the complementary comparison value for paths specified with `where()`
439
442
  *
440
- * ####Example
443
+ * #### Example
441
444
  *
442
445
  * User.where('age').equals(49);
443
446
  *
@@ -456,9 +459,9 @@ Query.prototype._validateOp = function() {
456
459
  /**
457
460
  * Specifies arguments for an `$or` condition.
458
461
  *
459
- * ####Example
462
+ * #### Example
460
463
  *
461
- * query.or([{ color: 'red' }, { status: 'emergency' }])
464
+ * query.or([{ color: 'red' }, { status: 'emergency' }]);
462
465
  *
463
466
  * @see $or https://docs.mongodb.org/manual/reference/operator/or/
464
467
  * @method or
@@ -472,9 +475,9 @@ Query.prototype._validateOp = function() {
472
475
  /**
473
476
  * Specifies arguments for a `$nor` condition.
474
477
  *
475
- * ####Example
478
+ * #### Example
476
479
  *
477
- * query.nor([{ color: 'green' }, { status: 'ok' }])
480
+ * query.nor([{ color: 'green' }, { status: 'ok' }]);
478
481
  *
479
482
  * @see $nor https://docs.mongodb.org/manual/reference/operator/nor/
480
483
  * @method nor
@@ -488,7 +491,7 @@ Query.prototype._validateOp = function() {
488
491
  /**
489
492
  * Specifies arguments for a `$and` condition.
490
493
  *
491
- * ####Example
494
+ * #### Example
492
495
  *
493
496
  * query.and([{ color: 'green' }, { status: 'ok' }])
494
497
  *
@@ -506,12 +509,12 @@ Query.prototype._validateOp = function() {
506
509
  *
507
510
  * When called with one argument, the most recent path passed to `where()` is used.
508
511
  *
509
- * ####Example
512
+ * #### Example
510
513
  *
511
- * Thing.find().where('age').gt(21)
514
+ * Thing.find().where('age').gt(21);
512
515
  *
513
516
  * // or
514
- * Thing.find().gt('age', 21)
517
+ * Thing.find().gt('age', 21);
515
518
  *
516
519
  * @method gt
517
520
  * @memberOf Query
@@ -611,7 +614,7 @@ Query.prototype._validateOp = function() {
611
614
  *
612
615
  * When called with one argument, the most recent path passed to `where()` is used.
613
616
  *
614
- * ####Example:
617
+ * #### Example:
615
618
  *
616
619
  * MyModel.find().where('pets').all(['dog', 'cat', 'ferret']);
617
620
  * // Equivalent:
@@ -631,7 +634,7 @@ Query.prototype._validateOp = function() {
631
634
  *
632
635
  * When called with one argument, the most recent path passed to `where()` is used.
633
636
  *
634
- * ####Example
637
+ * #### Example
635
638
  *
636
639
  * const docs = await MyModel.where('tags').size(0).exec();
637
640
  * assert(Array.isArray(docs));
@@ -678,7 +681,7 @@ Query.prototype._validateOp = function() {
678
681
  * Specifies a `$mod` condition, filters documents for documents whose
679
682
  * `path` property is a number that is equal to `remainder` modulo `divisor`.
680
683
  *
681
- * ####Example
684
+ * #### Example
682
685
  *
683
686
  * // All find products whose inventory is odd
684
687
  * Product.find().mod('inventory', [2, 1]);
@@ -724,7 +727,7 @@ Query.prototype.mod = function() {
724
727
  /**
725
728
  * Specifies an `$exists` condition
726
729
  *
727
- * ####Example
730
+ * #### Example
728
731
  *
729
732
  * // { name: { $exists: true }}
730
733
  * Thing.where('name').exists()
@@ -748,7 +751,7 @@ Query.prototype.mod = function() {
748
751
  /**
749
752
  * Specifies an `$elemMatch` condition
750
753
  *
751
- * ####Example
754
+ * #### Example
752
755
  *
753
756
  * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
754
757
  *
@@ -777,7 +780,7 @@ Query.prototype.mod = function() {
777
780
  /**
778
781
  * Defines a `$within` or `$geoWithin` argument for geo-spatial queries.
779
782
  *
780
- * ####Example
783
+ * #### Example
781
784
  *
782
785
  * query.where(path).within().box()
783
786
  * query.where(path).within().circle()
@@ -793,11 +796,11 @@ Query.prototype.mod = function() {
793
796
  *
794
797
  * **MUST** be used after `where()`.
795
798
  *
796
- * ####NOTE:
799
+ * #### Note:
797
800
  *
798
801
  * As of Mongoose 3.7, `$geoWithin` is always used for queries. To change this behavior, see [Query.use$geoWithin](#query_Query-use%2524geoWithin).
799
802
  *
800
- * ####NOTE:
803
+ * #### Note:
801
804
  *
802
805
  * In Mongoose 3.7, `within` changed from a getter to a function. If you need the old syntax, use [this](https://github.com/ebensing/mongoose-within).
803
806
  *
@@ -816,11 +819,11 @@ Query.prototype.mod = function() {
816
819
  /**
817
820
  * Specifies the maximum number of documents the query will return.
818
821
  *
819
- * ####Example
822
+ * #### Example
820
823
  *
821
- * query.limit(20)
824
+ * query.limit(20);
822
825
  *
823
- * ####Note
826
+ * #### Note
824
827
  *
825
828
  * Cannot be used with `distinct()`
826
829
  *
@@ -849,11 +852,11 @@ Query.prototype.limit = function limit(v) {
849
852
  /**
850
853
  * Specifies the number of documents to skip.
851
854
  *
852
- * ####Example
855
+ * #### Example
853
856
  *
854
- * query.skip(100).limit(20)
857
+ * query.skip(100).limit(20);
855
858
  *
856
- * ####Note
859
+ * #### Note
857
860
  *
858
861
  * Cannot be used with `distinct()`
859
862
  *
@@ -883,11 +886,11 @@ Query.prototype.skip = function skip(v) {
883
886
  /**
884
887
  * Specifies the maxScan option.
885
888
  *
886
- * ####Example
889
+ * #### Example
887
890
  *
888
- * query.maxScan(100)
891
+ * query.maxScan(100);
889
892
  *
890
- * ####Note
893
+ * #### Note
891
894
  *
892
895
  * Cannot be used with `distinct()`
893
896
  *
@@ -902,11 +905,11 @@ Query.prototype.skip = function skip(v) {
902
905
  /**
903
906
  * Specifies the batchSize option.
904
907
  *
905
- * ####Example
908
+ * #### Example
906
909
  *
907
910
  * query.batchSize(100)
908
911
  *
909
- * ####Note
912
+ * #### Note
910
913
  *
911
914
  * Cannot be used with `distinct()`
912
915
  *
@@ -921,11 +924,11 @@ Query.prototype.skip = function skip(v) {
921
924
  /**
922
925
  * Specifies the `comment` option.
923
926
  *
924
- * ####Example
927
+ * #### Example
925
928
  *
926
929
  * query.comment('login query')
927
930
  *
928
- * ####Note
931
+ * #### Note
929
932
  *
930
933
  * Cannot be used with `distinct()`
931
934
  *
@@ -940,13 +943,13 @@ Query.prototype.skip = function skip(v) {
940
943
  /**
941
944
  * Specifies this query as a `snapshot` query.
942
945
  *
943
- * ####Example
946
+ * #### Example
944
947
  *
945
- * query.snapshot() // true
946
- * query.snapshot(true)
947
- * query.snapshot(false)
948
+ * query.snapshot(); // true
949
+ * query.snapshot(true);
950
+ * query.snapshot(false);
948
951
  *
949
- * ####Note
952
+ * #### Note
950
953
  *
951
954
  * Cannot be used with `distinct()`
952
955
  *
@@ -961,11 +964,11 @@ Query.prototype.skip = function skip(v) {
961
964
  /**
962
965
  * Sets query hints.
963
966
  *
964
- * ####Example
967
+ * #### Example
965
968
  *
966
- * query.hint({ indexA: 1, indexB: -1})
969
+ * query.hint({ indexA: 1, indexB: -1 });
967
970
  *
968
- * ####Note
971
+ * #### Note
969
972
  *
970
973
  * Cannot be used with `distinct()`
971
974
  *
@@ -985,7 +988,7 @@ Query.prototype.skip = function skip(v) {
985
988
  * Unlike `projection()`, the `select()` function modifies the current
986
989
  * projection in place. This function overwrites the existing projection.
987
990
  *
988
- * ####Example:
991
+ * #### Example:
989
992
  *
990
993
  * const q = Model.find();
991
994
  * q.projection(); // null
@@ -1028,7 +1031,7 @@ Query.prototype.projection = function(arg) {
1028
1031
  * either list the fields to include (which excludes all others), or list the fields
1029
1032
  * to exclude (which implies all other fields are included). The [`_id` field is the only exception because MongoDB includes it by default](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/#suppress-id-field).
1030
1033
  *
1031
- * ####Example
1034
+ * #### Example
1032
1035
  *
1033
1036
  * // include a and b, exclude other fields
1034
1037
  * query.select('a b');
@@ -1139,49 +1142,30 @@ Query.prototype.select = function select() {
1139
1142
  throw new TypeError('Invalid select() argument. Must be string or object.');
1140
1143
  };
1141
1144
 
1142
- /**
1143
- * _DEPRECATED_ Sets the slaveOk option.
1144
- *
1145
- * **Deprecated** in MongoDB 2.2 in favor of [read preferences](#query_Query-read).
1146
- *
1147
- * ####Example:
1148
- *
1149
- * query.slaveOk() // true
1150
- * query.slaveOk(true)
1151
- * query.slaveOk(false)
1152
- *
1153
- * @method slaveOk
1154
- * @memberOf Query
1155
- * @instance
1156
- * @deprecated use read() preferences instead if on mongodb >= 2.2
1157
- * @param {Boolean} v defaults to true
1158
- * @see mongodb https://docs.mongodb.org/manual/applications/replication/#read-preference
1159
- * @see slaveOk https://docs.mongodb.org/manual/reference/method/rs.slaveOk/
1160
- * @see read() #query_Query-read
1161
- * @return {Query} this
1162
- * @api public
1163
- */
1164
-
1165
1145
  /**
1166
1146
  * Determines the MongoDB nodes from which to read.
1167
1147
  *
1168
- * ####Preferences:
1148
+ * #### Preferences:
1169
1149
  *
1170
- * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
1171
- * secondary Read from secondary if available, otherwise error.
1172
- * primaryPreferred Read from primary if available, otherwise a secondary.
1173
- * secondaryPreferred Read from a secondary if available, otherwise read from the primary.
1174
- * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
1150
+ * ```
1151
+ * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
1152
+ * secondary Read from secondary if available, otherwise error.
1153
+ * primaryPreferred Read from primary if available, otherwise a secondary.
1154
+ * secondaryPreferred Read from a secondary if available, otherwise read from the primary.
1155
+ * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
1156
+ * ```
1175
1157
  *
1176
1158
  * Aliases
1177
1159
  *
1178
- * p primary
1179
- * pp primaryPreferred
1180
- * s secondary
1181
- * sp secondaryPreferred
1182
- * n nearest
1160
+ * ```
1161
+ * p primary
1162
+ * pp primaryPreferred
1163
+ * s secondary
1164
+ * sp secondaryPreferred
1165
+ * n nearest
1166
+ * ```
1183
1167
  *
1184
- * ####Example:
1168
+ * #### Example:
1185
1169
  *
1186
1170
  * new Query().read('primary')
1187
1171
  * new Query().read('p') // same as primary
@@ -1260,7 +1244,7 @@ Query.prototype.toString = function toString() {
1260
1244
  *
1261
1245
  * Calling `session(null)` removes the session from this query.
1262
1246
  *
1263
- * ####Example:
1247
+ * #### Example:
1264
1248
  *
1265
1249
  * const s = await mongoose.startSession();
1266
1250
  * await mongoose.model('Person').findOne({ name: 'Axl Rose' }).session(s);
@@ -1304,7 +1288,7 @@ Query.prototype.session = function session(v) {
1304
1288
  *
1305
1289
  * Defaults to the schema's [`writeConcern` option](/docs/guide.html#writeConcern)
1306
1290
  *
1307
- * ####Example:
1291
+ * #### Example:
1308
1292
  *
1309
1293
  * // The 'majority' option means the `deleteOne()` promise won't resolve
1310
1294
  * // until the `deleteOne()` has propagated to the majority of the replica set
@@ -1347,7 +1331,7 @@ Query.prototype.writeConcern = function writeConcern(val) {
1347
1331
  *
1348
1332
  * Defaults to the schema's [`writeConcern.w` option](/docs/guide.html#writeConcern)
1349
1333
  *
1350
- * ####Example:
1334
+ * #### Example:
1351
1335
  *
1352
1336
  * // The 'majority' option means the `deleteOne()` promise won't resolve
1353
1337
  * // until the `deleteOne()` has propagated to the majority of the replica set
@@ -1393,7 +1377,7 @@ Query.prototype.w = function w(val) {
1393
1377
  *
1394
1378
  * Defaults to the schema's [`writeConcern.j` option](/docs/guide.html#writeConcern)
1395
1379
  *
1396
- * ####Example:
1380
+ * #### Example:
1397
1381
  *
1398
1382
  * await mongoose.model('Person').deleteOne({ name: 'Ned Stark' }).j(true);
1399
1383
  *
@@ -1437,7 +1421,7 @@ Query.prototype.j = function j(val) {
1437
1421
  *
1438
1422
  * Defaults to the schema's [`writeConcern.wtimeout` option](/docs/guide.html#writeConcern)
1439
1423
  *
1440
- * ####Example:
1424
+ * #### Example:
1441
1425
  *
1442
1426
  * // The `deleteOne()` promise won't resolve until this `deleteOne()` has
1443
1427
  * // propagated to at least `w = 2` members of the replica set. If it takes
@@ -1471,7 +1455,7 @@ Query.prototype.wtimeout = function wtimeout(ms) {
1471
1455
  /**
1472
1456
  * Sets the readConcern option for the query.
1473
1457
  *
1474
- * ####Example:
1458
+ * #### Example:
1475
1459
  *
1476
1460
  * new Query().readConcern('local')
1477
1461
  * new Query().readConcern('l') // same as local
@@ -1489,21 +1473,25 @@ Query.prototype.wtimeout = function wtimeout(ms) {
1489
1473
  * new Query().readConcern('s') // same as snapshot
1490
1474
  *
1491
1475
  *
1492
- * ####Read Concern Level:
1476
+ * #### Read Concern Level:
1493
1477
  *
1494
- * local MongoDB 3.2+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
1495
- * available MongoDB 3.6+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
1496
- * majority MongoDB 3.2+ The query returns the data that has been acknowledged by a majority of the replica set members. The documents returned by the read operation are durable, even in the event of failure.
1497
- * linearizable MongoDB 3.4+ The query returns data that reflects all successful majority-acknowledged writes that completed prior to the start of the read operation. The query may wait for concurrently executing writes to propagate to a majority of replica set members before returning results.
1498
- * snapshot MongoDB 4.0+ Only available for operations within multi-document transactions. Upon transaction commit with write concern "majority", the transaction operations are guaranteed to have read from a snapshot of majority-committed data.
1478
+ * ```
1479
+ * local MongoDB 3.2+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
1480
+ * available MongoDB 3.6+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
1481
+ * majority MongoDB 3.2+ The query returns the data that has been acknowledged by a majority of the replica set members. The documents returned by the read operation are durable, even in the event of failure.
1482
+ * linearizable MongoDB 3.4+ The query returns data that reflects all successful majority-acknowledged writes that completed prior to the start of the read operation. The query may wait for concurrently executing writes to propagate to a majority of replica set members before returning results.
1483
+ * snapshot MongoDB 4.0+ Only available for operations within multi-document transactions. Upon transaction commit with write concern "majority", the transaction operations are guaranteed to have read from a snapshot of majority-committed data.
1484
+ * ```
1499
1485
  *
1500
1486
  * Aliases
1501
1487
  *
1502
- * l local
1503
- * a available
1504
- * m majority
1505
- * lz linearizable
1506
- * s snapshot
1488
+ * ```
1489
+ * l local
1490
+ * a available
1491
+ * m majority
1492
+ * lz linearizable
1493
+ * s snapshot
1494
+ * ```
1507
1495
  *
1508
1496
  * Read more about how to use read concern [here](https://docs.mongodb.com/manual/reference/read-concern/).
1509
1497
  *
@@ -1518,11 +1506,11 @@ Query.prototype.wtimeout = function wtimeout(ms) {
1518
1506
  /**
1519
1507
  * Gets query options.
1520
1508
  *
1521
- * ####Example:
1509
+ * #### Example:
1522
1510
  *
1523
1511
  * const query = new Query();
1524
1512
  * query.limit(10);
1525
- * query.setOptions({ maxTimeMS: 1000 })
1513
+ * query.setOptions({ maxTimeMS: 1000 });
1526
1514
  * query.getOptions(); // { limit: 10, maxTimeMS: 1000 }
1527
1515
  *
1528
1516
  * @return {Object} the options
@@ -1536,7 +1524,7 @@ Query.prototype.getOptions = function() {
1536
1524
  /**
1537
1525
  * Sets query options. Some options only make sense for certain operations.
1538
1526
  *
1539
- * ####Options:
1527
+ * #### Options:
1540
1528
  *
1541
1529
  * The following options are only for `find()`:
1542
1530
  *
@@ -1678,7 +1666,7 @@ Query.prototype.setOptions = function(options, overwrite) {
1678
1666
  *
1679
1667
  * Calling `query.explain(v)` is equivalent to `query.setOptions({ explain: v })`
1680
1668
  *
1681
- * ####Example:
1669
+ * #### Example:
1682
1670
  *
1683
1671
  * const query = new Query();
1684
1672
  * const res = await query.find({ a: 1 }).explain('queryPlanner');
@@ -1710,7 +1698,7 @@ Query.prototype.explain = function(verbose) {
1710
1698
  *
1711
1699
  * Calling `query.allowDiskUse(v)` is equivalent to `query.setOptions({ allowDiskUse: v })`
1712
1700
  *
1713
- * ####Example:
1701
+ * #### Example:
1714
1702
  *
1715
1703
  * await query.find().sort({ name: 1 }).allowDiskUse(true);
1716
1704
  * // Equivalent:
@@ -1739,7 +1727,7 @@ Query.prototype.allowDiskUse = function(v) {
1739
1727
  *
1740
1728
  * Calling `query.maxTimeMS(v)` is equivalent to `query.setOptions({ maxTimeMS: v })`
1741
1729
  *
1742
- * ####Example:
1730
+ * #### Example:
1743
1731
  *
1744
1732
  * const query = new Query();
1745
1733
  * // Throws an error 'operation exceeded time limit' as long as there's
@@ -1759,7 +1747,7 @@ Query.prototype.maxTimeMS = function(ms) {
1759
1747
  /**
1760
1748
  * Returns the current query filter (also known as conditions) as a [POJO](https://masteringjs.io/tutorials/fundamentals/pojo).
1761
1749
  *
1762
- * ####Example:
1750
+ * #### Example:
1763
1751
  *
1764
1752
  * const query = new Query();
1765
1753
  * query.find({ a: 1 }).where('b').gt(2);
@@ -1779,7 +1767,7 @@ Query.prototype.getFilter = function() {
1779
1767
  * You should use `getFilter()` instead of `getQuery()` where possible. `getQuery()`
1780
1768
  * will likely be deprecated in a future release.
1781
1769
  *
1782
- * ####Example:
1770
+ * #### Example:
1783
1771
  *
1784
1772
  * const query = new Query();
1785
1773
  * query.find({ a: 1 }).where('b').gt(2);
@@ -1796,7 +1784,7 @@ Query.prototype.getQuery = function() {
1796
1784
  /**
1797
1785
  * Sets the query conditions to the provided JSON object.
1798
1786
  *
1799
- * ####Example:
1787
+ * #### Example:
1800
1788
  *
1801
1789
  * const query = new Query();
1802
1790
  * query.find({ a: 1 })
@@ -1815,7 +1803,7 @@ Query.prototype.setQuery = function(val) {
1815
1803
  /**
1816
1804
  * Returns the current update operations as a JSON object.
1817
1805
  *
1818
- * ####Example:
1806
+ * #### Example:
1819
1807
  *
1820
1808
  * const query = new Query();
1821
1809
  * query.update({}, { $set: { a: 5 } });
@@ -1832,7 +1820,7 @@ Query.prototype.getUpdate = function() {
1832
1820
  /**
1833
1821
  * Sets the current update operation to new value.
1834
1822
  *
1835
- * ####Example:
1823
+ * #### Example:
1836
1824
  *
1837
1825
  * const query = new Query();
1838
1826
  * query.update({}, { $set: { a: 5 } });
@@ -1985,7 +1973,7 @@ Query.prototype._optionsForExec = function(model) {
1985
1973
  * javascript objects, not [Mongoose Documents](/api/document.html). They have no
1986
1974
  * `save` method, getters/setters, virtuals, or other Mongoose features.
1987
1975
  *
1988
- * ####Example:
1976
+ * #### Example:
1989
1977
  *
1990
1978
  * new Query().lean() // true
1991
1979
  * new Query().lean(true)
@@ -2020,7 +2008,7 @@ Query.prototype.lean = function(v) {
2020
2008
  * This is useful for query middleware so you can add an update regardless
2021
2009
  * of whether you use `updateOne()`, `updateMany()`, `findOneAndUpdate()`, etc.
2022
2010
  *
2023
- * ####Example:
2011
+ * #### Example:
2024
2012
  *
2025
2013
  * // Updates `{ $set: { updatedAt: new Date() } }`
2026
2014
  * new Query().updateOne({}, {}).set('updatedAt', new Date());
@@ -2052,7 +2040,7 @@ Query.prototype.set = function(path, val) {
2052
2040
  * Useful for writing getters/setters that can work with both update operations
2053
2041
  * and `save()`.
2054
2042
  *
2055
- * ####Example:
2043
+ * #### Example:
2056
2044
  *
2057
2045
  * const query = Model.updateOne({}, { $set: { name: 'Jean-Luc Picard' } });
2058
2046
  * query.get('name'); // 'Jean-Luc Picard'
@@ -2086,7 +2074,7 @@ Query.prototype.get = function get(path) {
2086
2074
  * Gets/sets the error flag on this query. If this flag is not null or
2087
2075
  * undefined, the `exec()` promise will reject without executing.
2088
2076
  *
2089
- * ####Example:
2077
+ * #### Example:
2090
2078
  *
2091
2079
  * Query().error(); // Get current error value
2092
2080
  * Query().error(null); // Unset the current error
@@ -2100,7 +2088,7 @@ Query.prototype.get = function get(path) {
2100
2088
  * Note that query casting runs **after** hooks, so cast errors will override
2101
2089
  * custom errors.
2102
2090
  *
2103
- * ####Example:
2091
+ * #### Example:
2104
2092
  * const TestSchema = new Schema({ num: Number });
2105
2093
  * const TestModel = db.model('Test', TestSchema);
2106
2094
  * TestModel.find({ num: 'not a number' }).error(new Error('woops')).exec(function(error) {
@@ -2204,6 +2192,7 @@ function _castArrayFilters(query) {
2204
2192
  * @api private
2205
2193
  */
2206
2194
  Query.prototype._find = wrapThunk(function(callback) {
2195
+
2207
2196
  this._castConditions();
2208
2197
 
2209
2198
  if (this.error() != null) {
@@ -2222,6 +2211,7 @@ Query.prototype._find = wrapThunk(function(callback) {
2222
2211
  const userProvidedFields = _this._userProvidedFields || {};
2223
2212
 
2224
2213
  applyGlobalMaxTimeMS(this.options, this.model);
2214
+ applyGlobalDiskUse(this.options, this.model);
2225
2215
 
2226
2216
  // Separate options to pass down to `completeMany()` in case we need to
2227
2217
  // set a session on the document
@@ -2240,8 +2230,15 @@ Query.prototype._find = wrapThunk(function(callback) {
2240
2230
  if (this.options.explain) {
2241
2231
  return callback(null, docs);
2242
2232
  }
2243
-
2244
2233
  if (!mongooseOptions.populate) {
2234
+ const versionKey = _this.schema.options.versionKey;
2235
+ if (mongooseOptions.lean && mongooseOptions.lean.versionKey === false && versionKey) {
2236
+ docs.forEach((doc) => {
2237
+ if (versionKey in doc) {
2238
+ delete doc[versionKey];
2239
+ }
2240
+ });
2241
+ }
2245
2242
  return mongooseOptions.lean ?
2246
2243
  callback(null, docs) :
2247
2244
  completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions, callback);
@@ -2287,7 +2284,7 @@ Query.prototype._find = wrapThunk(function(callback) {
2287
2284
  * If there are too many documents in the result to fit in memory, use
2288
2285
  * [`Query.prototype.cursor()`](api.html#query_Query-cursor)
2289
2286
  *
2290
- * ####Example
2287
+ * #### Example
2291
2288
  *
2292
2289
  * // Using async/await
2293
2290
  * const arr = await Movie.find({ year: { $gte: 1980, $lte: 1989 } });
@@ -2423,6 +2420,12 @@ Query.prototype._completeOne = function(doc, res, callback) {
2423
2420
  }
2424
2421
 
2425
2422
  if (!mongooseOptions.populate) {
2423
+ const versionKey = this.schema.options.versionKey;
2424
+ if (mongooseOptions.lean && mongooseOptions.lean.versionKey === false && versionKey) {
2425
+ if (versionKey in doc) {
2426
+ delete doc[versionKey];
2427
+ }
2428
+ }
2426
2429
  return mongooseOptions.lean ?
2427
2430
  _completeOneLean(doc, res, options, callback) :
2428
2431
  completeOne(model, doc, res, options, projection, userProvidedFields,
@@ -2465,8 +2468,8 @@ Query.prototype._findOne = wrapThunk(function(callback) {
2465
2468
 
2466
2469
  this._applyPaths();
2467
2470
  this._fields = this._castFields(this._fields);
2468
-
2469
2471
  applyGlobalMaxTimeMS(this.options, this.model);
2472
+ applyGlobalDiskUse(this.options, this.model);
2470
2473
 
2471
2474
  // don't pass in the conditions because we already merged them in
2472
2475
  Query.base.findOne.call(this, {}, (err, doc) => {
@@ -2493,7 +2496,7 @@ Query.prototype._findOne = wrapThunk(function(callback) {
2493
2496
  *
2494
2497
  * - `findOne()`
2495
2498
  *
2496
- * ####Example
2499
+ * #### Example
2497
2500
  *
2498
2501
  * const query = Kitten.where({ color: 'white' });
2499
2502
  * query.findOne(function (err, kitten) {
@@ -2579,6 +2582,7 @@ Query.prototype._count = wrapThunk(function(callback) {
2579
2582
  }
2580
2583
 
2581
2584
  applyGlobalMaxTimeMS(this.options, this.model);
2585
+ applyGlobalDiskUse(this.options, this.model);
2582
2586
 
2583
2587
  const conds = this._conditions;
2584
2588
  const options = this._optionsForExec();
@@ -2606,6 +2610,7 @@ Query.prototype._countDocuments = wrapThunk(function(callback) {
2606
2610
  }
2607
2611
 
2608
2612
  applyGlobalMaxTimeMS(this.options, this.model);
2613
+ applyGlobalDiskUse(this.options, this.model);
2609
2614
 
2610
2615
  const conds = this._conditions;
2611
2616
  const options = this._optionsForExec();
@@ -2644,7 +2649,7 @@ Query.prototype._estimatedDocumentCount = wrapThunk(function(callback) {
2644
2649
  *
2645
2650
  * - `count()`
2646
2651
  *
2647
- * ####Example:
2652
+ * #### Example:
2648
2653
  *
2649
2654
  * const countQuery = model.where({ 'color': 'black' }).count();
2650
2655
  *
@@ -2701,7 +2706,7 @@ Query.prototype.count = function(filter, callback) {
2701
2706
  *
2702
2707
  * - `estimatedDocumentCount()`
2703
2708
  *
2704
- * ####Example:
2709
+ * #### Example:
2705
2710
  *
2706
2711
  * await Model.find().estimatedDocumentCount();
2707
2712
  *
@@ -2747,7 +2752,7 @@ Query.prototype.estimatedDocumentCount = function(options, callback) {
2747
2752
  *
2748
2753
  * - `countDocuments()`
2749
2754
  *
2750
- * ####Example:
2755
+ * #### Example:
2751
2756
  *
2752
2757
  * const countQuery = model.where({ 'color': 'black' }).countDocuments();
2753
2758
  *
@@ -2826,6 +2831,7 @@ Query.prototype.__distinct = wrapThunk(function __distinct(callback) {
2826
2831
  }
2827
2832
 
2828
2833
  applyGlobalMaxTimeMS(this.options, this.model);
2834
+ applyGlobalDiskUse(this.options, this.model);
2829
2835
 
2830
2836
  const options = this._optionsForExec();
2831
2837
 
@@ -2841,7 +2847,7 @@ Query.prototype.__distinct = wrapThunk(function __distinct(callback) {
2841
2847
  *
2842
2848
  * This function does not trigger any middleware.
2843
2849
  *
2844
- * ####Example
2850
+ * #### Example
2845
2851
  *
2846
2852
  * distinct(field, conditions, callback)
2847
2853
  * distinct(field, conditions)
@@ -2902,7 +2908,7 @@ Query.prototype.distinct = function(field, conditions, callback) {
2902
2908
  * sort order of each path is ascending unless the path name is prefixed with `-`
2903
2909
  * which will be treated as descending.
2904
2910
  *
2905
- * ####Example
2911
+ * #### Example
2906
2912
  *
2907
2913
  * // sort by "field" ascending and "test" descending
2908
2914
  * query.sort({ field: 'asc', test: -1 });
@@ -2910,7 +2916,7 @@ Query.prototype.distinct = function(field, conditions, callback) {
2910
2916
  * // equivalent
2911
2917
  * query.sort('field -test');
2912
2918
  *
2913
- * ####Note
2919
+ * #### Note
2914
2920
  *
2915
2921
  * Cannot be used with `distinct()`
2916
2922
  *
@@ -2935,7 +2941,7 @@ Query.prototype.sort = function(arg) {
2935
2941
  *
2936
2942
  * This function does not trigger any middleware
2937
2943
  *
2938
- * ####Example
2944
+ * #### Example
2939
2945
  *
2940
2946
  * Character.remove({ name: /Stark/ }, callback);
2941
2947
  *
@@ -2947,13 +2953,13 @@ Query.prototype.sort = function(arg) {
2947
2953
  * - `deletedCount`: the number of documents deleted
2948
2954
  * - `n`: the number of documents deleted. Equal to `deletedCount`.
2949
2955
  *
2950
- * ####Example
2956
+ * #### Example
2951
2957
  *
2952
2958
  * const res = await Character.remove({ name: /Stark/ });
2953
2959
  * // Number of docs deleted
2954
2960
  * res.deletedCount;
2955
2961
  *
2956
- * ####Note
2962
+ * #### Note
2957
2963
  *
2958
2964
  * Calling `remove()` creates a [Mongoose query](./queries.html), and a query
2959
2965
  * does not execute until you either pass a callback, call [`Query#then()`](#query_Query-then),
@@ -3027,7 +3033,7 @@ Query.prototype._remove = wrapThunk(function(callback) {
3027
3033
  *
3028
3034
  * This function triggers `deleteOne` middleware.
3029
3035
  *
3030
- * ####Example
3036
+ * #### Example
3031
3037
  *
3032
3038
  * await Character.deleteOne({ name: 'Eddard Stark' });
3033
3039
  *
@@ -3042,7 +3048,7 @@ Query.prototype._remove = wrapThunk(function(callback) {
3042
3048
  * - `deletedCount`: the number of documents deleted
3043
3049
  * - `n`: the number of documents deleted. Equal to `deletedCount`.
3044
3050
  *
3045
- * ####Example
3051
+ * #### Example
3046
3052
  *
3047
3053
  * const res = await Character.deleteOne({ name: 'Eddard Stark' });
3048
3054
  * // `1` if MongoDB deleted a doc, `0` if no docs matched the filter `{ name: ... }`
@@ -3113,7 +3119,7 @@ Query.prototype._deleteOne = wrapThunk(function(callback) {
3113
3119
  *
3114
3120
  * This function triggers `deleteMany` middleware.
3115
3121
  *
3116
- * ####Example
3122
+ * #### Example
3117
3123
  *
3118
3124
  * await Character.deleteMany({ name: /Stark/, age: { $gte: 18 } });
3119
3125
  *
@@ -3128,7 +3134,7 @@ Query.prototype._deleteOne = wrapThunk(function(callback) {
3128
3134
  * - `deletedCount`: the number of documents deleted
3129
3135
  * - `n`: the number of documents deleted. Equal to `deletedCount`.
3130
3136
  *
3131
- * ####Example
3137
+ * #### Example
3132
3138
  *
3133
3139
  * const res = await Character.deleteMany({ name: /Stark/, age: { $gte: 18 } });
3134
3140
  * // `0` if no docs matched the filter, number of docs deleted otherwise
@@ -3263,7 +3269,7 @@ function prepareDiscriminatorCriteria(query) {
3263
3269
  *
3264
3270
  * - `findOneAndUpdate()`
3265
3271
  *
3266
- * ####Available options
3272
+ * #### Available options
3267
3273
  *
3268
3274
  * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
3269
3275
  * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
@@ -3274,13 +3280,13 @@ function prepareDiscriminatorCriteria(query) {
3274
3280
  * - `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.
3275
3281
  * - `rawResult`: if true, returns the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3276
3282
  *
3277
- * ####Callback Signature
3283
+ * #### Callback Signature
3278
3284
  * function(error, doc) {
3279
3285
  * // error: any errors that occurred
3280
3286
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3281
3287
  * }
3282
3288
  *
3283
- * ####Examples
3289
+ * #### Examples
3284
3290
  *
3285
3291
  * query.findOneAndUpdate(conditions, update, options, callback) // executes
3286
3292
  * query.findOneAndUpdate(conditions, update, options) // returns Query
@@ -3410,19 +3416,19 @@ Query.prototype._findOneAndUpdate = wrapThunk(function(callback) {
3410
3416
  *
3411
3417
  * - `findOneAndRemove()`
3412
3418
  *
3413
- * ####Available options
3419
+ * #### Available options
3414
3420
  *
3415
3421
  * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
3416
3422
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
3417
3423
  * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3418
3424
  *
3419
- * ####Callback Signature
3425
+ * #### Callback Signature
3420
3426
  * function(error, doc) {
3421
3427
  * // error: any errors that occurred
3422
3428
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3423
3429
  * }
3424
3430
  *
3425
- * ####Examples
3431
+ * #### Examples
3426
3432
  *
3427
3433
  * A.where().findOneAndRemove(conditions, options, callback) // executes
3428
3434
  * A.where().findOneAndRemove(conditions, options) // return Query
@@ -3497,19 +3503,19 @@ Query.prototype.findOneAndRemove = function(conditions, options, callback) {
3497
3503
  * this distinction is purely pedantic. You should use `findOneAndDelete()`
3498
3504
  * unless you have a good reason not to.
3499
3505
  *
3500
- * ####Available options
3506
+ * #### Available options
3501
3507
  *
3502
3508
  * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
3503
3509
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
3504
3510
  * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3505
3511
  *
3506
- * ####Callback Signature
3512
+ * #### Callback Signature
3507
3513
  * function(error, doc) {
3508
3514
  * // error: any errors that occurred
3509
3515
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3510
3516
  * }
3511
3517
  *
3512
- * ####Examples
3518
+ * #### Examples
3513
3519
  *
3514
3520
  * A.where().findOneAndDelete(conditions, options, callback) // executes
3515
3521
  * A.where().findOneAndDelete(conditions, options) // return Query
@@ -3616,19 +3622,19 @@ Query.prototype._findOneAndDelete = wrapThunk(function(callback) {
3616
3622
  *
3617
3623
  * - `findOneAndReplace()`
3618
3624
  *
3619
- * ####Available options
3625
+ * #### Available options
3620
3626
  *
3621
3627
  * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
3622
3628
  * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
3623
3629
  * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.3/interfaces/ModifyResult.html)
3624
3630
  *
3625
- * ####Callback Signature
3631
+ * #### Callback Signature
3626
3632
  * function(error, doc) {
3627
3633
  * // error: any errors that occurred
3628
3634
  * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
3629
3635
  * }
3630
3636
  *
3631
- * ####Examples
3637
+ * #### Examples
3632
3638
  *
3633
3639
  * A.where().findOneAndReplace(filter, replacement, options, callback); // executes
3634
3640
  * A.where().findOneAndReplace(filter, replacement, options); // return Query
@@ -3726,7 +3732,6 @@ Query.prototype.findOneAndReplace = function(filter, replacement, options, callb
3726
3732
  */
3727
3733
  Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
3728
3734
  this._castConditions();
3729
-
3730
3735
  if (this.error() != null) {
3731
3736
  callback(this.error());
3732
3737
  return null;
@@ -3737,9 +3742,6 @@ Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
3737
3742
  convertNewToReturnDocument(options);
3738
3743
  let fields = null;
3739
3744
 
3740
- let castedDoc = new this.model(this._update, null, true);
3741
- this._update = castedDoc;
3742
-
3743
3745
  this._applyPaths();
3744
3746
  if (this._fields != null) {
3745
3747
  options.projection = this._castFields(utils.clone(this._fields));
@@ -3750,7 +3752,34 @@ Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
3750
3752
  }
3751
3753
  }
3752
3754
 
3753
- castedDoc.$validate(err => {
3755
+ const runValidators = _getOption(this, 'runValidators', false);
3756
+ if (runValidators === false) {
3757
+ try {
3758
+ this._update = this._castUpdate(this._update, true);
3759
+ } catch (err) {
3760
+ const validationError = new ValidationError();
3761
+ validationError.errors[err.path] = err;
3762
+ callback(validationError);
3763
+ return null;
3764
+ }
3765
+
3766
+ this._collection.collection.findOneAndReplace(filter, this._update || {}, options, _wrapThunkCallback(this, (err, res) => {
3767
+ if (err) {
3768
+ return callback(err);
3769
+ }
3770
+
3771
+ const doc = res.value;
3772
+
3773
+ return this._completeOne(doc, res, callback);
3774
+ }));
3775
+
3776
+ return;
3777
+ }
3778
+
3779
+
3780
+ let castedDoc = new this.model(this._update, null, true);
3781
+ this._update = castedDoc;
3782
+ castedDoc.validate(err => {
3754
3783
  if (err != null) {
3755
3784
  return callback(err);
3756
3785
  }
@@ -3873,7 +3902,11 @@ Query.prototype._findAndModify = function(type, callback) {
3873
3902
  }
3874
3903
 
3875
3904
  if (!isOverwriting) {
3876
- this._update = castDoc(this, opts.overwrite);
3905
+ try {
3906
+ this._update = this._castUpdate(this._update, opts.overwrite);
3907
+ } catch (err) {
3908
+ return callback(err);
3909
+ }
3877
3910
  const _opts = Object.assign({}, opts, {
3878
3911
  setDefaultsOnInsert: this._mongooseOptions.setDefaultsOnInsert
3879
3912
  });
@@ -4068,10 +4101,10 @@ function _updateThunk(op, callback) {
4068
4101
  }
4069
4102
  this._update = new this.model(this._update, null, true);
4070
4103
  } else {
4071
- this._update = castDoc(this, options.overwrite);
4072
-
4073
- if (this._update instanceof Error) {
4074
- callback(this._update);
4104
+ try {
4105
+ this._update = this._castUpdate(this._update, options.overwrite);
4106
+ } catch (err) {
4107
+ callback(err);
4075
4108
  return null;
4076
4109
  }
4077
4110
 
@@ -4193,15 +4226,15 @@ Query.prototype._replaceOne = wrapThunk(function(callback) {
4193
4226
  *
4194
4227
  * - `update()`
4195
4228
  *
4196
- * ####Example
4229
+ * #### Example
4197
4230
  *
4198
- * Model.where({ _id: id }).update({ title: 'words' })
4231
+ * Model.where({ _id: id }).update({ title: 'words' });
4199
4232
  *
4200
4233
  * // becomes
4201
4234
  *
4202
- * Model.where({ _id: id }).update({ $set: { title: 'words' }})
4235
+ * Model.where({ _id: id }).update({ $set: { title: 'words' }});
4203
4236
  *
4204
- * ####Valid options:
4237
+ * #### Valid options:
4205
4238
  *
4206
4239
  * - `upsert` (boolean) whether to create the doc if it doesn't match (false)
4207
4240
  * - `multi` (boolean) whether multiple documents should be updated (false)
@@ -4211,47 +4244,51 @@ Query.prototype._replaceOne = wrapThunk(function(callback) {
4211
4244
  * - `read`
4212
4245
  * - `writeConcern`
4213
4246
  *
4214
- * ####Note
4247
+ * #### Note
4215
4248
  *
4216
4249
  * Passing an empty object `{}` as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB.
4217
4250
  *
4218
- * ####Note
4251
+ * #### Note
4219
4252
  *
4220
4253
  * The operation is only executed when a callback is passed. To force execution without a callback, we must first call update() and then execute it by using the `exec()` method.
4221
4254
  *
4222
- * const q = Model.where({ _id: id });
4223
- * q.update({ $set: { name: 'bob' }}).update(); // not executed
4255
+ * ```javascript
4256
+ * const q = Model.where({ _id: id });
4257
+ * q.update({ $set: { name: 'bob' }}).update(); // not executed
4224
4258
  *
4225
- * q.update({ $set: { name: 'bob' }}).exec(); // executed
4259
+ * q.update({ $set: { name: 'bob' }}).exec(); // executed
4226
4260
  *
4227
- * // keys that are not [atomic](https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#pattern) ops become `$set`.
4228
- * // this executes the same command as the previous example.
4229
- * q.update({ name: 'bob' }).exec();
4261
+ * // keys that are not [atomic](https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#pattern) ops become `$set`.
4262
+ * // this executes the same command as the previous example.
4263
+ * q.update({ name: 'bob' }).exec();
4230
4264
  *
4231
- * // multi updates
4232
- * Model.where()
4233
- * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback)
4265
+ * // multi updates
4266
+ * Model.where()
4267
+ * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback)
4234
4268
  *
4235
- * // more multi updates
4236
- * Model.where()
4237
- * .setOptions({ multi: true })
4238
- * .update({ $set: { arr: [] }}, callback)
4269
+ * // more multi updates
4270
+ * Model.where()
4271
+ * .setOptions({ multi: true })
4272
+ * .update({ $set: { arr: [] }}, callback)
4239
4273
  *
4240
- * // single update by default
4241
- * Model.where({ email: 'address@example.com' })
4242
- * .update({ $inc: { counter: 1 }}, callback)
4274
+ * // single update by default
4275
+ * Model.where({ email: 'address@example.com' })
4276
+ * .update({ $inc: { counter: 1 }}, callback)
4277
+ * ```
4243
4278
  *
4244
4279
  * API summary
4245
4280
  *
4246
- * update(filter, doc, options, cb) // executes
4247
- * update(filter, doc, options)
4248
- * update(filter, doc, cb) // executes
4249
- * update(filter, doc)
4250
- * update(doc, cb) // executes
4251
- * update(doc)
4252
- * update(cb) // executes
4253
- * update(true) // executes
4254
- * update()
4281
+ * ```javascript
4282
+ * update(filter, doc, options, cb); // executes
4283
+ * update(filter, doc, options);
4284
+ * update(filter, doc, cb); // executes
4285
+ * update(filter, doc);
4286
+ * update(doc, cb); // executes
4287
+ * update(doc);
4288
+ * update(cb); // executes
4289
+ * update(true); // executes
4290
+ * update();
4291
+ * ```
4255
4292
  *
4256
4293
  * @param {Object} [filter]
4257
4294
  * @param {Object} [doc] the update command
@@ -4308,7 +4345,7 @@ Query.prototype.update = function(conditions, doc, options, callback) {
4308
4345
  * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')`
4309
4346
  * and `post('updateMany')` instead.
4310
4347
  *
4311
- * ####Example:
4348
+ * #### Example:
4312
4349
  * const res = await Person.updateMany({ name: /Stark$/ }, { isDeleted: true });
4313
4350
  * res.n; // Number of documents matched
4314
4351
  * res.nModified; // Number of documents modified
@@ -4373,7 +4410,7 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
4373
4410
  * **Note** updateOne will _not_ fire update middleware. Use `pre('updateOne')`
4374
4411
  * and `post('updateOne')` instead.
4375
4412
  *
4376
- * ####Example:
4413
+ * #### Example:
4377
4414
  * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
4378
4415
  * res.n; // Number of documents matched
4379
4416
  * res.nModified; // Number of documents modified
@@ -4436,7 +4473,7 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) {
4436
4473
  * **Note** replaceOne will _not_ fire update middleware. Use `pre('replaceOne')`
4437
4474
  * and `post('replaceOne')` instead.
4438
4475
  *
4439
- * ####Example:
4476
+ * #### Example:
4440
4477
  * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
4441
4478
  * res.n; // Number of documents matched
4442
4479
  * res.nModified; // Number of documents modified
@@ -4540,7 +4577,7 @@ function _update(query, op, filter, doc, options, callback) {
4540
4577
  *
4541
4578
  * Any functions you pass to `transform()` will run **after** any post hooks.
4542
4579
  *
4543
- * ####Example:
4580
+ * #### Example:
4544
4581
  *
4545
4582
  * const res = await MyModel.findOne().transform(res => {
4546
4583
  * // Sets a `loadedAt` property on the doc that tells you the time the
@@ -4567,7 +4604,7 @@ Query.prototype.transform = function(fn) {
4567
4604
  * This is handy for integrating with async/await, because `orFail()` saves you
4568
4605
  * an extra `if` statement to check if no document was found.
4569
4606
  *
4570
- * ####Example:
4607
+ * #### Example:
4571
4608
  *
4572
4609
  * // Throws if no doc returned
4573
4610
  * await Model.findOne({ foo: 'bar' }).orFail();
@@ -4657,7 +4694,7 @@ function _orFailError(err, query) {
4657
4694
  /**
4658
4695
  * Executes the query
4659
4696
  *
4660
- * ####Examples:
4697
+ * #### Examples:
4661
4698
  *
4662
4699
  * const promise = query.exec();
4663
4700
  * const promise = query.exec('update');
@@ -4797,7 +4834,7 @@ Query.prototype.catch = function(reject) {
4797
4834
  * Add pre [middleware](/docs/middleware.html) to this query instance. Doesn't affect
4798
4835
  * other queries.
4799
4836
  *
4800
- * ####Example:
4837
+ * #### Example:
4801
4838
  *
4802
4839
  * const q1 = Question.find({ answer: 42 });
4803
4840
  * q1.pre(function middleware() {
@@ -4823,7 +4860,7 @@ Query.prototype.pre = function(fn) {
4823
4860
  * Add post [middleware](/docs/middleware.html) to this query instance. Doesn't affect
4824
4861
  * other queries.
4825
4862
  *
4826
- * ####Example:
4863
+ * #### Example:
4827
4864
  *
4828
4865
  * const q1 = Question.find({ answer: 42 });
4829
4866
  * q1.post(function middleware() {
@@ -4906,23 +4943,10 @@ function castQuery(query) {
4906
4943
  }
4907
4944
  }
4908
4945
 
4909
- /*!
4910
- * castDoc
4911
- * @api private
4912
- */
4913
-
4914
- function castDoc(query, overwrite) {
4915
- try {
4916
- return query._castUpdate(query._update, overwrite);
4917
- } catch (err) {
4918
- return err;
4919
- }
4920
- }
4921
-
4922
4946
  /**
4923
4947
  * Specifies paths which should be populated with other documents.
4924
4948
  *
4925
- * ####Example:
4949
+ * #### Example:
4926
4950
  *
4927
4951
  * let book = await Book.findOne().populate('authors');
4928
4952
  * book.title; // 'Node.js in Action'
@@ -5029,14 +5053,14 @@ Query.prototype.populate = function() {
5029
5053
  /**
5030
5054
  * Gets a list of paths to be populated by this query
5031
5055
  *
5032
- * ####Example:
5056
+ * #### Example:
5033
5057
  * bookSchema.pre('findOne', function() {
5034
5058
  * let keys = this.getPopulatedPaths(); // ['author']
5035
5059
  * });
5036
5060
  * ...
5037
5061
  * Book.findOne({}).populate('author');
5038
5062
  *
5039
- * ####Example:
5063
+ * #### Example:
5040
5064
  * // Deep populate
5041
5065
  * const q = L1.find().populate({
5042
5066
  * path: 'level2',
@@ -5078,7 +5102,7 @@ function _getPopulatedPaths(list, arr, prefix) {
5078
5102
  /**
5079
5103
  * Casts this query to the schema of `model`
5080
5104
  *
5081
- * ####Note
5105
+ * #### Note
5082
5106
  *
5083
5107
  * If `obj` is present, it is cast instead of this query.
5084
5108
  *
@@ -5203,7 +5227,7 @@ Query.prototype._applyPaths = function applyPaths() {
5203
5227
  *
5204
5228
  * The `.cursor()` function triggers pre find hooks, but **not** post find hooks.
5205
5229
  *
5206
- * ####Example
5230
+ * #### Example
5207
5231
  *
5208
5232
  * // There are 2 ways to use a cursor. First, as a stream:
5209
5233
  * Thing.
@@ -5227,7 +5251,7 @@ Query.prototype._applyPaths = function applyPaths() {
5227
5251
  * console.log(doc);
5228
5252
  * }
5229
5253
  *
5230
- * ####Valid options
5254
+ * #### Valid options
5231
5255
  *
5232
5256
  * - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data` and returned by `.next()`.
5233
5257
  *
@@ -5274,7 +5298,7 @@ Query.prototype.maxscan = Query.base.maxScan;
5274
5298
  /**
5275
5299
  * Sets the tailable option (for use with capped collections).
5276
5300
  *
5277
- * ####Example
5301
+ * #### Example
5278
5302
  *
5279
5303
  * query.tailable(); // true
5280
5304
  * query.tailable(true);
@@ -5283,7 +5307,7 @@ Query.prototype.maxscan = Query.base.maxScan;
5283
5307
  * // Set both `tailable` and `awaitData` options
5284
5308
  * query.tailable({ awaitData: true });
5285
5309
  *
5286
- * ####Note
5310
+ * #### Note
5287
5311
  *
5288
5312
  * Cannot be used with `distinct()`
5289
5313
  *
@@ -5324,23 +5348,23 @@ Query.prototype.tailable = function(val, opts) {
5324
5348
  /**
5325
5349
  * Declares an intersects query for `geometry()`.
5326
5350
  *
5327
- * ####Example
5351
+ * #### Example
5328
5352
  *
5329
5353
  * query.where('path').intersects().geometry({
5330
- * type: 'LineString'
5331
- * , coordinates: [[180.0, 11.0], [180, 9.0]]
5332
- * })
5354
+ * type: 'LineString',
5355
+ * coordinates: [[180.0, 11.0], [180, 9.0]]
5356
+ * });
5333
5357
  *
5334
5358
  * query.where('path').intersects({
5335
- * type: 'LineString'
5336
- * , coordinates: [[180.0, 11.0], [180, 9.0]]
5337
- * })
5359
+ * type: 'LineString',
5360
+ * coordinates: [[180.0, 11.0], [180, 9.0]]
5361
+ * });
5338
5362
  *
5339
- * ####NOTE:
5363
+ * #### Note:
5340
5364
  *
5341
5365
  * **MUST** be used after `where()`.
5342
5366
  *
5343
- * ####NOTE:
5367
+ * #### Note:
5344
5368
  *
5345
5369
  * In Mongoose 3.7, `intersects` changed from a getter to a function. If you need the old syntax, use [this](https://github.com/ebensing/mongoose-within).
5346
5370
  *
@@ -5357,7 +5381,7 @@ Query.prototype.tailable = function(val, opts) {
5357
5381
  /**
5358
5382
  * Specifies a `$geometry` condition
5359
5383
  *
5360
- * ####Example
5384
+ * #### Example
5361
5385
  *
5362
5386
  * const polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]
5363
5387
  * query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA })
@@ -5375,7 +5399,7 @@ Query.prototype.tailable = function(val, opts) {
5375
5399
  *
5376
5400
  * The argument is assigned to the most recent path passed to `where()`.
5377
5401
  *
5378
- * ####NOTE:
5402
+ * #### Note:
5379
5403
  *
5380
5404
  * `geometry()` **must** come after either `intersects()` or `within()`.
5381
5405
  *
@@ -5399,7 +5423,7 @@ Query.prototype.tailable = function(val, opts) {
5399
5423
  *
5400
5424
  * These operators return documents sorted by distance.
5401
5425
  *
5402
- * ####Example
5426
+ * #### Example
5403
5427
  *
5404
5428
  * query.where('loc').near({ center: [10, 10] });
5405
5429
  * query.where('loc').near({ center: [10, 10], maxDistance: 5 });
@@ -5482,13 +5506,13 @@ Query.prototype.near = function() {
5482
5506
  /**
5483
5507
  * _DEPRECATED_ Specifies a `$nearSphere` condition
5484
5508
  *
5485
- * ####Example
5509
+ * #### Example
5486
5510
  *
5487
5511
  * query.where('loc').nearSphere({ center: [10, 10], maxDistance: 5 });
5488
5512
  *
5489
5513
  * **Deprecated.** Use `query.near()` instead with the `spherical` option set to `true`.
5490
5514
  *
5491
- * ####Example
5515
+ * #### Example
5492
5516
  *
5493
5517
  * query.where('loc').near({ center: [10, 10], spherical: true });
5494
5518
  *
@@ -5511,7 +5535,7 @@ Query.prototype.nearSphere = function() {
5511
5535
  * You do not need to call this function explicitly, the JavaScript runtime
5512
5536
  * will call it for you.
5513
5537
  *
5514
- * ####Example
5538
+ * #### Example
5515
5539
  *
5516
5540
  * for await (const doc of Model.aggregate([{ $sort: { name: 1 } }])) {
5517
5541
  * console.log(doc.name);
@@ -5539,10 +5563,10 @@ if (Symbol.asyncIterator != null) {
5539
5563
  /**
5540
5564
  * Specifies a `$polygon` condition
5541
5565
  *
5542
- * ####Example
5566
+ * #### Example
5543
5567
  *
5544
- * query.where('loc').within().polygon([10,20], [13, 25], [7,15])
5545
- * query.polygon('loc', [10,20], [13, 25], [7,15])
5568
+ * query.where('loc').within().polygon([10, 20], [13, 25], [7, 15]);
5569
+ * query.polygon('loc', [10, 20], [13, 25], [7, 15]);
5546
5570
  *
5547
5571
  * @method polygon
5548
5572
  * @memberOf Query
@@ -5558,7 +5582,7 @@ if (Symbol.asyncIterator != null) {
5558
5582
  /**
5559
5583
  * Specifies a `$box` condition
5560
5584
  *
5561
- * ####Example
5585
+ * #### Example
5562
5586
  *
5563
5587
  * const lowerLeft = [40.73083, -73.99756]
5564
5588
  * const upperRight= [40.741404, -73.988135]
@@ -5595,7 +5619,7 @@ Query.prototype.box = function(ll, ur) {
5595
5619
  /**
5596
5620
  * Specifies a `$center` or `$centerSphere` condition.
5597
5621
  *
5598
- * ####Example
5622
+ * #### Example
5599
5623
  *
5600
5624
  * const area = { center: [50, 50], radius: 10, unique: true }
5601
5625
  * query.where('loc').within().circle(area)
@@ -5640,7 +5664,7 @@ Query.prototype.center = Query.base.circle;
5640
5664
  *
5641
5665
  * **Deprecated.** Use [circle](#query_Query-circle) instead.
5642
5666
  *
5643
- * ####Example
5667
+ * #### Example
5644
5668
  *
5645
5669
  * const area = { center: [50, 50], radius: 10 };
5646
5670
  * query.where('loc').within().centerSphere(area);
@@ -5679,9 +5703,9 @@ Query.prototype.centerSphere = function() {
5679
5703
  /**
5680
5704
  * Determines if inclusive field selection has been made.
5681
5705
  *
5682
- * query.selectedInclusively() // false
5683
- * query.select('name')
5684
- * query.selectedInclusively() // true
5706
+ * query.selectedInclusively(); // false
5707
+ * query.select('name');
5708
+ * query.selectedInclusively(); // true
5685
5709
  *
5686
5710
  * @method selectedInclusively
5687
5711
  * @memberOf Query
@@ -5697,10 +5721,10 @@ Query.prototype.selectedInclusively = function selectedInclusively() {
5697
5721
  /**
5698
5722
  * Determines if exclusive field selection has been made.
5699
5723
  *
5700
- * query.selectedExclusively() // false
5701
- * query.select('-name')
5702
- * query.selectedExclusively() // true
5703
- * query.selectedInclusively() // false
5724
+ * query.selectedExclusively(); // false
5725
+ * query.select('-name');
5726
+ * query.selectedExclusively(); // true
5727
+ * query.selectedInclusively(); // false
5704
5728
  *
5705
5729
  * @method selectedExclusively
5706
5730
  * @memberOf Query