mongoose 6.4.6 → 6.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/aggregate.js +32 -30
- package/lib/browser.js +1 -1
- package/lib/cast.js +2 -2
- package/lib/collection.js +1 -1
- package/lib/connection.js +56 -18
- package/lib/cursor/ChangeStream.js +39 -1
- package/lib/document.js +293 -249
- package/lib/error/index.js +1 -0
- package/lib/error/validation.js +9 -0
- package/lib/helpers/document/applyDefaults.js +115 -0
- package/lib/helpers/document/cleanModifiedSubpaths.js +3 -3
- package/lib/helpers/document/compile.js +7 -6
- package/lib/helpers/firstKey.js +8 -0
- package/lib/helpers/model/applyDefaultsToPOJO.js +52 -0
- package/lib/helpers/model/castBulkWrite.js +1 -1
- package/lib/helpers/model/pushNestedArrayPaths.js +15 -0
- package/lib/helpers/populate/markArraySubdocsPopulated.js +1 -0
- package/lib/helpers/projection/hasIncludedChildren.js +1 -0
- package/lib/helpers/update/applyTimestampsToChildren.js +6 -2
- package/lib/index.js +3 -2
- package/lib/internal.js +3 -1
- package/lib/model.js +233 -94
- package/lib/options/SchemaArrayOptions.js +19 -0
- package/lib/options/SchemaNumberOptions.js +2 -0
- package/lib/options/SchemaObjectIdOptions.js +1 -0
- package/lib/plugins/trackTransaction.js +2 -2
- package/lib/query.js +24 -10
- package/lib/schema/SubdocumentPath.js +10 -0
- package/lib/schema/array.js +2 -1
- package/lib/schema/documentarray.js +14 -1
- package/lib/schema/string.js +3 -0
- package/lib/schema.js +22 -3
- package/lib/schematype.js +100 -82
- package/lib/statemachine.js +23 -9
- package/lib/types/buffer.js +21 -19
- package/lib/types/map.js +2 -0
- package/lib/utils.js +8 -0
- package/lib/validoptions.js +1 -0
- package/lib/virtualtype.js +14 -16
- package/package.json +12 -12
- package/types/connection.d.ts +2 -2
- package/types/document.d.ts +8 -1
- package/types/expressions.d.ts +1 -1
- package/types/index.d.ts +16 -25
- package/types/inferschematype.d.ts +3 -20
- package/types/models.d.ts +58 -54
- package/types/mongooseoptions.d.ts +6 -0
- package/types/schemaoptions.d.ts +15 -4
- package/types/utility.d.ts +19 -0
- package/types/virtuals.d.ts +14 -0
package/lib/aggregate.js
CHANGED
|
@@ -19,7 +19,7 @@ const validRedactStringValues = new Set(['$$DESCEND', '$$PRUNE', '$$KEEP']);
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Aggregate constructor used for building aggregation pipelines. Do not
|
|
22
|
-
* instantiate this class directly, use [Model.aggregate()](/docs/api.html#model_Model
|
|
22
|
+
* instantiate this class directly, use [Model.aggregate()](/docs/api.html#model_Model-aggregate) instead.
|
|
23
23
|
*
|
|
24
24
|
* #### Example:
|
|
25
25
|
*
|
|
@@ -38,11 +38,9 @@ const validRedactStringValues = new Set(['$$DESCEND', '$$PRUNE', '$$KEEP']);
|
|
|
38
38
|
* - The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
|
|
39
39
|
* - Mongoose does **not** cast pipeline stages. The below will **not** work unless `_id` is a string in the database
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* new Aggregate([{ $match: { _id: new mongoose.Types.ObjectId('00000000000000000000000a') } }]);
|
|
45
|
-
* ```
|
|
41
|
+
* new Aggregate([{ $match: { _id: '00000000000000000000000a' } }]);
|
|
42
|
+
* // Do this instead to cast to an ObjectId
|
|
43
|
+
* new Aggregate([{ $match: { _id: new mongoose.Types.ObjectId('00000000000000000000000a') } }]);
|
|
46
44
|
*
|
|
47
45
|
* @see MongoDB https://docs.mongodb.org/manual/applications/aggregation/
|
|
48
46
|
* @see driver https://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate
|
|
@@ -72,8 +70,8 @@ function Aggregate(pipeline, model) {
|
|
|
72
70
|
* - [`cursor`](./api.html#aggregate_Aggregate-cursor)
|
|
73
71
|
* - [`explain`](./api.html#aggregate_Aggregate-explain)
|
|
74
72
|
* - `fieldsAsRaw`
|
|
75
|
-
* - hint
|
|
76
|
-
* - let
|
|
73
|
+
* - `hint`
|
|
74
|
+
* - `let`
|
|
77
75
|
* - `maxTimeMS`
|
|
78
76
|
* - `raw`
|
|
79
77
|
* - `readConcern`
|
|
@@ -92,6 +90,7 @@ Aggregate.prototype.options;
|
|
|
92
90
|
* Get/set the model that this aggregation will execute on.
|
|
93
91
|
*
|
|
94
92
|
* #### Example:
|
|
93
|
+
*
|
|
95
94
|
* const aggregate = MyModel.aggregate([{ $match: { answer: 42 } }]);
|
|
96
95
|
* aggregate.model() === MyModel; // true
|
|
97
96
|
*
|
|
@@ -99,7 +98,7 @@ Aggregate.prototype.options;
|
|
|
99
98
|
* aggregate.model(SomeOtherModel);
|
|
100
99
|
* aggregate.model() === SomeOtherModel; // true
|
|
101
100
|
*
|
|
102
|
-
* @param {Model} [model]
|
|
101
|
+
* @param {Model} [model] Set the model associated with this aggregate. If not provided, returns the already stored model.
|
|
103
102
|
* @return {Model}
|
|
104
103
|
* @api public
|
|
105
104
|
*/
|
|
@@ -135,7 +134,7 @@ Aggregate.prototype.model = function(model) {
|
|
|
135
134
|
* const pipeline = [{ $match: { daw: 'Logic Audio X' }} ];
|
|
136
135
|
* aggregate.append(pipeline);
|
|
137
136
|
*
|
|
138
|
-
* @param {Object} ops operator(s) to append
|
|
137
|
+
* @param {...Object|Object[]} ops operator(s) to append. Can either be a spread of objects or a single parameter of a object array.
|
|
139
138
|
* @return {Aggregate}
|
|
140
139
|
* @api public
|
|
141
140
|
*/
|
|
@@ -364,7 +363,7 @@ Aggregate.prototype.near = function(arg) {
|
|
|
364
363
|
* aggregate.unwind({ path: '$tags', preserveNullAndEmptyArrays: true });
|
|
365
364
|
*
|
|
366
365
|
* @see $unwind https://docs.mongodb.org/manual/reference/aggregation/unwind/
|
|
367
|
-
* @param {String|Object} fields the field(s) to unwind, either as field names or as [objects with options](https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/#document-operand-with-options). If passing a string, prefixing the field name with '$' is optional. If passing an object, `path` must start with '$'.
|
|
366
|
+
* @param {String|Object|String[]|Object[]} fields the field(s) to unwind, either as field names or as [objects with options](https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/#document-operand-with-options). If passing a string, prefixing the field name with '$' is optional. If passing an object, `path` must start with '$'.
|
|
368
367
|
* @return {Aggregate}
|
|
369
368
|
* @api public
|
|
370
369
|
*/
|
|
@@ -495,6 +494,7 @@ Aggregate.prototype.lookup = function(options) {
|
|
|
495
494
|
* Note that graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified.
|
|
496
495
|
*
|
|
497
496
|
* #### Examples:
|
|
497
|
+
*
|
|
498
498
|
* // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }`
|
|
499
499
|
* aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites
|
|
500
500
|
*
|
|
@@ -602,7 +602,8 @@ Aggregate.prototype.sort = function(arg) {
|
|
|
602
602
|
*
|
|
603
603
|
* @see $unionWith https://docs.mongodb.com/manual/reference/operator/aggregation/unionWith
|
|
604
604
|
* @param {Object} options to $unionWith query as described in the above link
|
|
605
|
-
* @return {Aggregate}
|
|
605
|
+
* @return {Aggregate}
|
|
606
|
+
* @api public
|
|
606
607
|
*/
|
|
607
608
|
|
|
608
609
|
Aggregate.prototype.unionWith = function(options) {
|
|
@@ -617,8 +618,8 @@ Aggregate.prototype.unionWith = function(options) {
|
|
|
617
618
|
*
|
|
618
619
|
* await Model.aggregate(pipeline).read('primaryPreferred');
|
|
619
620
|
*
|
|
620
|
-
* @param {String} pref one of the listed preference options or their aliases
|
|
621
|
-
* @param {Array} [tags] optional tags for this query
|
|
621
|
+
* @param {String|ReadPreference} pref one of the listed preference options or their aliases
|
|
622
|
+
* @param {Array} [tags] optional tags for this query. DEPRECATED
|
|
622
623
|
* @return {Aggregate} this
|
|
623
624
|
* @api public
|
|
624
625
|
* @see mongodb https://docs.mongodb.org/manual/applications/replication/#read-preference
|
|
@@ -703,9 +704,9 @@ Aggregate.prototype.redact = function(expression, thenExpr, elseExpr) {
|
|
|
703
704
|
*
|
|
704
705
|
* Model.aggregate(..).explain(callback)
|
|
705
706
|
*
|
|
706
|
-
* @param {String} verbosity
|
|
707
|
-
* @param {Function} callback
|
|
708
|
-
* @return {Promise}
|
|
707
|
+
* @param {String} [verbosity]
|
|
708
|
+
* @param {Function} [callback] The callback function to call, if not specified, will return a Promise instead.
|
|
709
|
+
* @return {Promise} Returns a promise if no "callback" is given
|
|
709
710
|
*/
|
|
710
711
|
|
|
711
712
|
Aggregate.prototype.explain = function(verbosity, callback) {
|
|
@@ -772,6 +773,7 @@ Aggregate.prototype.explain = function(verbosity, callback) {
|
|
|
772
773
|
* await Model.aggregate([{ $match: { foo: 'bar' } }]).allowDiskUse(true);
|
|
773
774
|
*
|
|
774
775
|
* @param {Boolean} value Should tell server it can use hard drive to store data during aggregation.
|
|
776
|
+
* @return {Aggregate} this
|
|
775
777
|
* @see mongodb https://docs.mongodb.org/manual/reference/command/aggregate/
|
|
776
778
|
*/
|
|
777
779
|
|
|
@@ -788,6 +790,7 @@ Aggregate.prototype.allowDiskUse = function(value) {
|
|
|
788
790
|
* Model.aggregate(..).hint({ qty: 1, category: 1 }).exec(callback)
|
|
789
791
|
*
|
|
790
792
|
* @param {Object|String} value a hint object or the index name
|
|
793
|
+
* @return {Aggregate} this
|
|
791
794
|
* @see mongodb https://docs.mongodb.org/manual/reference/command/aggregate/
|
|
792
795
|
*/
|
|
793
796
|
|
|
@@ -805,6 +808,7 @@ Aggregate.prototype.hint = function(value) {
|
|
|
805
808
|
* await Model.aggregate(..).session(session);
|
|
806
809
|
*
|
|
807
810
|
* @param {ClientSession} session
|
|
811
|
+
* @return {Aggregate} this
|
|
808
812
|
* @see mongodb https://docs.mongodb.org/manual/reference/command/aggregate/
|
|
809
813
|
*/
|
|
810
814
|
|
|
@@ -826,10 +830,10 @@ Aggregate.prototype.session = function(session) {
|
|
|
826
830
|
* agg.options; // `{ allowDiskUse: true }`
|
|
827
831
|
*
|
|
828
832
|
* @param {Object} options keys to merge into current options
|
|
829
|
-
* @param [options.maxTimeMS] number limits the time this aggregation will run, see [MongoDB docs on `maxTimeMS`](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/)
|
|
830
|
-
* @param [options.allowDiskUse] boolean if true, the MongoDB server will use the hard drive to store data during this aggregation
|
|
831
|
-
* @param [options.collation] object see [`Aggregate.prototype.collation()`](./docs/api.html#aggregate_Aggregate-collation)
|
|
832
|
-
* @param [options.session] ClientSession see [`Aggregate.prototype.session()`](./docs/api.html#aggregate_Aggregate-session)
|
|
833
|
+
* @param {Number} [options.maxTimeMS] number limits the time this aggregation will run, see [MongoDB docs on `maxTimeMS`](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/)
|
|
834
|
+
* @param {Boolean} [options.allowDiskUse] boolean if true, the MongoDB server will use the hard drive to store data during this aggregation
|
|
835
|
+
* @param {Object} [options.collation] object see [`Aggregate.prototype.collation()`](./docs/api.html#aggregate_Aggregate-collation)
|
|
836
|
+
* @param {ClientSession} [options.session] ClientSession see [`Aggregate.prototype.session()`](./docs/api.html#aggregate_Aggregate-session)
|
|
833
837
|
* @see mongodb https://docs.mongodb.org/manual/reference/command/aggregate/
|
|
834
838
|
* @return {Aggregate} this
|
|
835
839
|
* @api public
|
|
@@ -855,7 +859,7 @@ Aggregate.prototype.option = function(value) {
|
|
|
855
859
|
* });
|
|
856
860
|
*
|
|
857
861
|
* @param {Object} options
|
|
858
|
-
* @param {Number} options.batchSize set the cursor batch size
|
|
862
|
+
* @param {Number} [options.batchSize] set the cursor batch size
|
|
859
863
|
* @param {Boolean} [options.useMongooseAggCursor] use experimental mongoose-specific aggregation cursor (for `eachAsync()` and other query cursor semantics)
|
|
860
864
|
* @return {AggregationCursor} cursor representing this aggregation
|
|
861
865
|
* @api public
|
|
@@ -940,11 +944,10 @@ Aggregate.prototype.search = function(options) {
|
|
|
940
944
|
*
|
|
941
945
|
* MyModel.aggregate().match({ test: 1 }).pipeline(); // [{ $match: { test: 1 } }]
|
|
942
946
|
*
|
|
943
|
-
* @return {Array}
|
|
947
|
+
* @return {Array} The current pipeline similar to the operation that will be executed
|
|
944
948
|
* @api public
|
|
945
949
|
*/
|
|
946
950
|
|
|
947
|
-
|
|
948
951
|
Aggregate.prototype.pipeline = function() {
|
|
949
952
|
return this._pipeline;
|
|
950
953
|
};
|
|
@@ -957,12 +960,10 @@ Aggregate.prototype.pipeline = function() {
|
|
|
957
960
|
* aggregate.exec(callback);
|
|
958
961
|
*
|
|
959
962
|
* // Because a promise is returned, the `callback` is optional.
|
|
960
|
-
* const
|
|
961
|
-
* promise.then(..);
|
|
963
|
+
* const result = await aggregate.exec();
|
|
962
964
|
*
|
|
963
|
-
* @see Promise #promise_Promise
|
|
964
965
|
* @param {Function} [callback]
|
|
965
|
-
* @return {Promise}
|
|
966
|
+
* @return {Promise} Returns a Promise if no "callback" is given.
|
|
966
967
|
* @api public
|
|
967
968
|
*/
|
|
968
969
|
|
|
@@ -1018,13 +1019,13 @@ Aggregate.prototype.exec = function(callback) {
|
|
|
1018
1019
|
};
|
|
1019
1020
|
|
|
1020
1021
|
/**
|
|
1021
|
-
* Provides
|
|
1022
|
+
* Provides a Promise-like `then` function, which will call `.exec` without a callback
|
|
1023
|
+
* Compatible with `await`.
|
|
1022
1024
|
*
|
|
1023
1025
|
* #### Example:
|
|
1024
1026
|
*
|
|
1025
1027
|
* Model.aggregate(..).then(successCallback, errorCallback);
|
|
1026
1028
|
*
|
|
1027
|
-
* @see Promise #promise_Promise
|
|
1028
1029
|
* @param {Function} [resolve] successCallback
|
|
1029
1030
|
* @param {Function} [reject] errorCallback
|
|
1030
1031
|
* @return {Promise}
|
|
@@ -1037,6 +1038,7 @@ Aggregate.prototype.then = function(resolve, reject) {
|
|
|
1037
1038
|
* Executes the query returning a `Promise` which will be
|
|
1038
1039
|
* resolved with either the doc(s) or rejected with the error.
|
|
1039
1040
|
* Like [`.then()`](#query_Query-then), but only takes a rejection handler.
|
|
1041
|
+
* Compatible with `await`.
|
|
1040
1042
|
*
|
|
1041
1043
|
* @param {Function} [reject]
|
|
1042
1044
|
* @return {Promise}
|
package/lib/browser.js
CHANGED
|
@@ -103,7 +103,7 @@ exports.VirtualType = require('./virtualtype');
|
|
|
103
103
|
* _Alias of mongoose.Schema.Types for backwards compatibility._
|
|
104
104
|
*
|
|
105
105
|
* @property SchemaTypes
|
|
106
|
-
* @see Schema.SchemaTypes #schema_Schema
|
|
106
|
+
* @see Schema.SchemaTypes #schema_Schema-Types
|
|
107
107
|
* @api public
|
|
108
108
|
*/
|
|
109
109
|
|
package/lib/cast.js
CHANGED
|
@@ -24,8 +24,8 @@ const ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon'];
|
|
|
24
24
|
*
|
|
25
25
|
* @param {Schema} schema
|
|
26
26
|
* @param {Object} obj Object to cast
|
|
27
|
-
* @param {Object} options the query options
|
|
28
|
-
* @param {Query} context passed to setters
|
|
27
|
+
* @param {Object} [options] the query options
|
|
28
|
+
* @param {Query} [context] passed to setters
|
|
29
29
|
* @api private
|
|
30
30
|
*/
|
|
31
31
|
module.exports = function cast(schema, obj, options, context) {
|
package/lib/collection.js
CHANGED
|
@@ -15,7 +15,7 @@ const immediate = require('./helpers/immediate');
|
|
|
15
15
|
*
|
|
16
16
|
* @param {String} name name of the collection
|
|
17
17
|
* @param {Connection} conn A MongooseConnection instance
|
|
18
|
-
* @param {Object} opts optional collection options
|
|
18
|
+
* @param {Object} [opts] optional collection options
|
|
19
19
|
* @api public
|
|
20
20
|
*/
|
|
21
21
|
|
package/lib/connection.js
CHANGED
|
@@ -393,7 +393,7 @@ Connection.prototype.config;
|
|
|
393
393
|
* @param {string} collection The collection to create
|
|
394
394
|
* @param {Object} [options] see [MongoDB driver docs](https://mongodb.github.io/node-mongodb-native/2.2/api/Db.html#createCollection)
|
|
395
395
|
* @param {Function} [callback]
|
|
396
|
-
* @return {Promise}
|
|
396
|
+
* @return {Promise} Returns a Promise if no `callback` is given.
|
|
397
397
|
* @api public
|
|
398
398
|
*/
|
|
399
399
|
|
|
@@ -491,6 +491,9 @@ Connection.prototype.transaction = function transaction(fn, options) {
|
|
|
491
491
|
doc.set(doc.schema.options.versionKey, state.versionKey);
|
|
492
492
|
}
|
|
493
493
|
|
|
494
|
+
if (state.modifiedPaths.length > 0 && doc.$__.activePaths.states.modify == null) {
|
|
495
|
+
doc.$__.activePaths.states.modify = {};
|
|
496
|
+
}
|
|
494
497
|
for (const path of state.modifiedPaths) {
|
|
495
498
|
doc.$__.activePaths.paths[path] = 'modify';
|
|
496
499
|
doc.$__.activePaths.states.modify[path] = true;
|
|
@@ -521,7 +524,7 @@ Connection.prototype.transaction = function transaction(fn, options) {
|
|
|
521
524
|
* @method dropCollection
|
|
522
525
|
* @param {string} collection The collection to delete
|
|
523
526
|
* @param {Function} [callback]
|
|
524
|
-
* @return {Promise}
|
|
527
|
+
* @return {Promise} Returns a Promise if no `callback` is given.
|
|
525
528
|
* @api public
|
|
526
529
|
*/
|
|
527
530
|
|
|
@@ -541,7 +544,7 @@ Connection.prototype.dropCollection = _wrapConnHelper(function dropCollection(co
|
|
|
541
544
|
*
|
|
542
545
|
* @method dropDatabase
|
|
543
546
|
* @param {Function} [callback]
|
|
544
|
-
* @return {Promise}
|
|
547
|
+
* @return {Promise} Returns a Promise if no `callback` is given.
|
|
545
548
|
* @api public
|
|
546
549
|
*/
|
|
547
550
|
|
|
@@ -550,8 +553,8 @@ Connection.prototype.dropDatabase = _wrapConnHelper(function dropDatabase(cb) {
|
|
|
550
553
|
// init-ed. It is sufficiently common to call `dropDatabase()` after
|
|
551
554
|
// `mongoose.connect()` but before creating models that we want to
|
|
552
555
|
// support this. See gh-6796
|
|
553
|
-
for (const
|
|
554
|
-
delete
|
|
556
|
+
for (const model of Object.values(this.models)) {
|
|
557
|
+
delete model.$init;
|
|
555
558
|
}
|
|
556
559
|
this.db.dropDatabase(cb);
|
|
557
560
|
});
|
|
@@ -608,6 +611,8 @@ Connection.prototype._shouldBufferCommands = function _shouldBufferCommands() {
|
|
|
608
611
|
*
|
|
609
612
|
* @param {Error} err
|
|
610
613
|
* @param {Function} callback optional
|
|
614
|
+
* @emits "error" Emits the `error` event with the given `err`, unless a callback is specified
|
|
615
|
+
* @returns {Promise|null} Returns a rejected Promise if no `callback` is given.
|
|
611
616
|
* @api private
|
|
612
617
|
*/
|
|
613
618
|
|
|
@@ -668,7 +673,7 @@ Connection.prototype.onOpen = function() {
|
|
|
668
673
|
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
|
669
674
|
* @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
|
670
675
|
* @param {Function} [callback]
|
|
671
|
-
* @returns {Connection}
|
|
676
|
+
* @returns {Promise<Connection>} Returns a Promise if no `callback` is given.
|
|
672
677
|
* @api public
|
|
673
678
|
*/
|
|
674
679
|
|
|
@@ -838,6 +843,11 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
838
843
|
);
|
|
839
844
|
}
|
|
840
845
|
|
|
846
|
+
for (const model of Object.values(this.models)) {
|
|
847
|
+
// Errors handled internally, so safe to ignore error
|
|
848
|
+
model.init(function $modelInitNoop() {});
|
|
849
|
+
}
|
|
850
|
+
|
|
841
851
|
return this.$initialConnection;
|
|
842
852
|
};
|
|
843
853
|
|
|
@@ -913,6 +923,14 @@ function _setClient(conn, client, options, dbName) {
|
|
|
913
923
|
}
|
|
914
924
|
}
|
|
915
925
|
|
|
926
|
+
/**
|
|
927
|
+
* Destory the connection (not just a alias of [`.close`](#connection_Connection-close))
|
|
928
|
+
*
|
|
929
|
+
* @param {Boolean} [force]
|
|
930
|
+
* @param {Function} [callback]
|
|
931
|
+
* @returns {Promise} Returns a Promise if no `callback` is given.
|
|
932
|
+
*/
|
|
933
|
+
|
|
916
934
|
Connection.prototype.destroy = function(force, callback) {
|
|
917
935
|
if (typeof force === 'function') {
|
|
918
936
|
callback = force;
|
|
@@ -935,7 +953,7 @@ Connection.prototype.destroy = function(force, callback) {
|
|
|
935
953
|
*
|
|
936
954
|
* @param {Boolean} [force] optional
|
|
937
955
|
* @param {Function} [callback] optional
|
|
938
|
-
* @return {Promise}
|
|
956
|
+
* @return {Promise} Returns a Promise if no `callback` is given.
|
|
939
957
|
* @api public
|
|
940
958
|
*/
|
|
941
959
|
|
|
@@ -951,6 +969,13 @@ Connection.prototype.close = function(force, callback) {
|
|
|
951
969
|
this.$wasForceClosed = !!force;
|
|
952
970
|
}
|
|
953
971
|
|
|
972
|
+
for (const model of Object.values(this.models)) {
|
|
973
|
+
// If manually disconnecting, make sure to clear each model's `$init`
|
|
974
|
+
// promise, so Mongoose knows to re-run `init()` in case the
|
|
975
|
+
// connection is re-opened. See gh-12047.
|
|
976
|
+
delete model.$init;
|
|
977
|
+
}
|
|
978
|
+
|
|
954
979
|
return promiseOrCallback(callback, cb => {
|
|
955
980
|
this._close(force, false, cb);
|
|
956
981
|
});
|
|
@@ -961,7 +986,8 @@ Connection.prototype.close = function(force, callback) {
|
|
|
961
986
|
*
|
|
962
987
|
* @param {Boolean} force
|
|
963
988
|
* @param {Boolean} destroy
|
|
964
|
-
* @param {Function} callback
|
|
989
|
+
* @param {Function} [callback]
|
|
990
|
+
* @returns {Connection} this
|
|
965
991
|
* @api private
|
|
966
992
|
*/
|
|
967
993
|
Connection.prototype._close = function(force, destroy, callback) {
|
|
@@ -1081,6 +1107,7 @@ Connection.prototype.collection = function(name, options) {
|
|
|
1081
1107
|
* Equivalent to calling `.plugin(fn)` on each schema you create.
|
|
1082
1108
|
*
|
|
1083
1109
|
* #### Example:
|
|
1110
|
+
*
|
|
1084
1111
|
* const db = mongoose.createConnection('mongodb://localhost:27017/mydb');
|
|
1085
1112
|
* db.plugin(() => console.log('Applied'));
|
|
1086
1113
|
* db.plugins.length; // 1
|
|
@@ -1108,7 +1135,7 @@ Connection.prototype.plugin = function(fn, opts) {
|
|
|
1108
1135
|
* const Ticket = db.model('Ticket', new Schema(..));
|
|
1109
1136
|
* const Venue = db.model('Venue');
|
|
1110
1137
|
*
|
|
1111
|
-
* _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils_exports
|
|
1138
|
+
* _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils_exports-toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._
|
|
1112
1139
|
*
|
|
1113
1140
|
* #### Example:
|
|
1114
1141
|
*
|
|
@@ -1274,7 +1301,7 @@ Connection.prototype.deleteModel = function(name) {
|
|
|
1274
1301
|
|
|
1275
1302
|
/**
|
|
1276
1303
|
* Watches the entire underlying database for changes. Similar to
|
|
1277
|
-
* [`Model.watch()`](/docs/api/model.html#model_Model
|
|
1304
|
+
* [`Model.watch()`](/docs/api/model.html#model_Model-watch).
|
|
1278
1305
|
*
|
|
1279
1306
|
* This function does **not** trigger any middleware. In particular, it
|
|
1280
1307
|
* does **not** trigger aggregate middleware.
|
|
@@ -1330,6 +1357,7 @@ Connection.prototype.watch = function(pipeline, options) {
|
|
|
1330
1357
|
* to connect.
|
|
1331
1358
|
*
|
|
1332
1359
|
* #### Example:
|
|
1360
|
+
*
|
|
1333
1361
|
* const conn = await mongoose.createConnection('mongodb://localhost:27017/test').
|
|
1334
1362
|
* asPromise();
|
|
1335
1363
|
* conn.readyState; // 1, means Mongoose is connected
|
|
@@ -1345,7 +1373,7 @@ Connection.prototype.asPromise = function asPromise() {
|
|
|
1345
1373
|
/**
|
|
1346
1374
|
* Returns an array of model names created on this connection.
|
|
1347
1375
|
* @api public
|
|
1348
|
-
* @return {
|
|
1376
|
+
* @return {String[]}
|
|
1349
1377
|
*/
|
|
1350
1378
|
|
|
1351
1379
|
Connection.prototype.modelNames = function() {
|
|
@@ -1353,9 +1381,10 @@ Connection.prototype.modelNames = function() {
|
|
|
1353
1381
|
};
|
|
1354
1382
|
|
|
1355
1383
|
/**
|
|
1356
|
-
*
|
|
1384
|
+
* Returns if the connection requires authentication after it is opened. Generally if a
|
|
1357
1385
|
* username and password are both provided than authentication is needed, but in some cases a
|
|
1358
1386
|
* password is not required.
|
|
1387
|
+
*
|
|
1359
1388
|
* @api private
|
|
1360
1389
|
* @return {Boolean} true if the connection should be authenticated after it is opened, otherwise false.
|
|
1361
1390
|
*/
|
|
@@ -1365,8 +1394,9 @@ Connection.prototype.shouldAuthenticate = function() {
|
|
|
1365
1394
|
};
|
|
1366
1395
|
|
|
1367
1396
|
/**
|
|
1368
|
-
*
|
|
1397
|
+
* Returns a boolean value that specifies if the current authentication mechanism needs a
|
|
1369
1398
|
* password to authenticate according to the auth objects passed into the openUri methods.
|
|
1399
|
+
*
|
|
1370
1400
|
* @api private
|
|
1371
1401
|
* @return {Boolean} true if the authentication mechanism specified in the options object requires
|
|
1372
1402
|
* a password, otherwise false.
|
|
@@ -1379,10 +1409,11 @@ Connection.prototype.authMechanismDoesNotRequirePassword = function() {
|
|
|
1379
1409
|
};
|
|
1380
1410
|
|
|
1381
1411
|
/**
|
|
1382
|
-
*
|
|
1412
|
+
* Returns a boolean value that specifies if the provided objects object provides enough
|
|
1383
1413
|
* data to authenticate with. Generally this is true if the username and password are both specified
|
|
1384
1414
|
* but in some authentication methods, a password is not required for authentication so only a username
|
|
1385
1415
|
* is required.
|
|
1416
|
+
*
|
|
1386
1417
|
* @param {Object} [options] the options object passed into the openUri methods.
|
|
1387
1418
|
* @api private
|
|
1388
1419
|
* @return {Boolean} true if the provided options object provides enough data to authenticate with,
|
|
@@ -1399,6 +1430,7 @@ Connection.prototype.optionsProvideAuthenticationData = function(options) {
|
|
|
1399
1430
|
* that this connection uses to talk to MongoDB.
|
|
1400
1431
|
*
|
|
1401
1432
|
* #### Example:
|
|
1433
|
+
*
|
|
1402
1434
|
* const conn = await mongoose.createConnection('mongodb://localhost:27017/test').
|
|
1403
1435
|
* asPromise();
|
|
1404
1436
|
*
|
|
@@ -1418,6 +1450,7 @@ Connection.prototype.getClient = function getClient() {
|
|
|
1418
1450
|
* reuse it.
|
|
1419
1451
|
*
|
|
1420
1452
|
* #### Example:
|
|
1453
|
+
*
|
|
1421
1454
|
* const client = await mongodb.MongoClient.connect('mongodb://localhost:27017/test');
|
|
1422
1455
|
*
|
|
1423
1456
|
* const conn = mongoose.createConnection().setClient(client);
|
|
@@ -1426,6 +1459,7 @@ Connection.prototype.getClient = function getClient() {
|
|
|
1426
1459
|
* conn.readyState; // 1, means 'CONNECTED'
|
|
1427
1460
|
*
|
|
1428
1461
|
* @api public
|
|
1462
|
+
* @param {MongClient} client The Client to set to be used.
|
|
1429
1463
|
* @return {Connection} this
|
|
1430
1464
|
*/
|
|
1431
1465
|
|
|
@@ -1443,16 +1477,20 @@ Connection.prototype.setClient = function setClient(client) {
|
|
|
1443
1477
|
this._connectionString = client.s.url;
|
|
1444
1478
|
_setClient(this, client, {}, client.s.options.dbName);
|
|
1445
1479
|
|
|
1480
|
+
for (const model of Object.values(this.models)) {
|
|
1481
|
+
// Errors handled internally, so safe to ignore error
|
|
1482
|
+
model.init(function $modelInitNoop() {});
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1446
1485
|
return this;
|
|
1447
1486
|
};
|
|
1448
1487
|
|
|
1449
1488
|
/**
|
|
1450
|
-
*
|
|
1451
1489
|
* Syncs all the indexes for the models registered with this connection.
|
|
1452
1490
|
*
|
|
1453
|
-
* @param {Object} options
|
|
1454
|
-
* @param {Boolean} options.continueOnError `false` by default. If set to `true`, mongoose will not throw an error if one model syncing failed, and will return an object where the keys are the names of the models, and the values are the results/errors for each model.
|
|
1455
|
-
* @return {Promise} Returns a Promise, when the Promise resolves the value is a list of the dropped indexes.
|
|
1491
|
+
* @param {Object} [options]
|
|
1492
|
+
* @param {Boolean} [options.continueOnError] `false` by default. If set to `true`, mongoose will not throw an error if one model syncing failed, and will return an object where the keys are the names of the models, and the values are the results/errors for each model.
|
|
1493
|
+
* @return {Promise<Object>} Returns a Promise, when the Promise resolves the value is a list of the dropped indexes.
|
|
1456
1494
|
*/
|
|
1457
1495
|
Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
|
|
1458
1496
|
const result = {};
|
|
@@ -20,6 +20,13 @@ class ChangeStream extends EventEmitter {
|
|
|
20
20
|
this.pipeline = pipeline;
|
|
21
21
|
this.options = options;
|
|
22
22
|
|
|
23
|
+
if (options && options.hydrate && !options.model) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
'Cannot create change stream with `hydrate: true` ' +
|
|
26
|
+
'unless calling `Model.watch()`'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
// This wrapper is necessary because of buffering.
|
|
24
31
|
changeStreamThunk((err, driverChangeStream) => {
|
|
25
32
|
if (err != null) {
|
|
@@ -46,7 +53,12 @@ class ChangeStream extends EventEmitter {
|
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
['close', 'change', 'end', 'error'].forEach(ev => {
|
|
49
|
-
this.driverChangeStream.on(ev, data =>
|
|
56
|
+
this.driverChangeStream.on(ev, data => {
|
|
57
|
+
if (data.fullDocument != null && this.options && this.options.hydrate) {
|
|
58
|
+
data.fullDocument = this.options.model.hydrate(data.fullDocument);
|
|
59
|
+
}
|
|
60
|
+
this.emit(ev, data);
|
|
61
|
+
});
|
|
50
62
|
});
|
|
51
63
|
});
|
|
52
64
|
|
|
@@ -69,6 +81,32 @@ class ChangeStream extends EventEmitter {
|
|
|
69
81
|
}
|
|
70
82
|
|
|
71
83
|
next(cb) {
|
|
84
|
+
if (this.options && this.options.hydrate) {
|
|
85
|
+
if (cb != null) {
|
|
86
|
+
const originalCb = cb;
|
|
87
|
+
cb = (err, data) => {
|
|
88
|
+
if (err != null) {
|
|
89
|
+
return originalCb(err);
|
|
90
|
+
}
|
|
91
|
+
if (data.fullDocument != null) {
|
|
92
|
+
data.fullDocument = this.options.model.hydrate(data.fullDocument);
|
|
93
|
+
}
|
|
94
|
+
return originalCb(null, data);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let maybePromise = this.driverChangeStream.next(cb);
|
|
99
|
+
if (maybePromise && typeof maybePromise.then === 'function') {
|
|
100
|
+
maybePromise = maybePromise.then(data => {
|
|
101
|
+
if (data.fullDocument != null) {
|
|
102
|
+
data.fullDocument = this.options.model.hydrate(data.fullDocument);
|
|
103
|
+
}
|
|
104
|
+
return data;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return maybePromise;
|
|
108
|
+
}
|
|
109
|
+
|
|
72
110
|
return this.driverChangeStream.next(cb);
|
|
73
111
|
}
|
|
74
112
|
|