mongoose 6.2.11 → 6.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +157 -157
- package/README.md +1 -1
- package/dist/browser.umd.js +2 -1704
- package/lib/aggregate.js +4 -3
- package/lib/collection.js +0 -7
- package/lib/connection.js +2 -1
- package/lib/cursor/ChangeStream.js +42 -2
- package/lib/cursor/QueryCursor.js +2 -0
- package/lib/document.js +22 -26
- package/lib/error/cast.js +8 -2
- package/lib/error/eachAsyncMultiError.js +41 -0
- package/lib/helpers/common.js +0 -8
- package/lib/helpers/cursor/eachAsync.js +44 -12
- package/lib/helpers/immediate.js +3 -1
- package/lib/helpers/isAsyncFunction.js +19 -7
- package/lib/helpers/model/discriminator.js +1 -3
- package/lib/helpers/populate/getModelsMapForPopulate.js +13 -10
- package/lib/helpers/query/applyGlobalOption.js +29 -0
- package/lib/helpers/schematype/handleImmutable.js +4 -1
- package/lib/helpers/timestamps/setupTimestamps.js +2 -2
- package/lib/index.js +11 -4
- package/lib/internal.js +0 -1
- package/lib/model.js +39 -27
- package/lib/query.js +23 -4
- package/lib/queryhelpers.js +11 -1
- package/lib/schema/SubdocumentPath.js +3 -15
- package/lib/schema/documentarray.js +7 -7
- package/lib/schema/number.js +1 -5
- package/lib/schema/objectid.js +2 -4
- package/lib/schema/string.js +1 -5
- package/lib/schema.js +115 -2
- package/lib/schematype.js +2 -2
- package/lib/types/DocumentArray/methods/index.js +9 -1
- package/lib/types/array/methods/index.js +8 -9
- package/lib/validoptions.js +1 -0
- package/package.json +25 -18
- package/tools/repl.js +2 -1
- package/tsconfig.json +2 -2
- package/types/aggregate.d.ts +1 -2
- package/types/connection.d.ts +4 -5
- package/types/cursor.d.ts +13 -6
- package/types/document.d.ts +17 -14
- package/types/error.d.ts +124 -124
- package/types/index.d.ts +350 -202
- package/types/mongooseoptions.d.ts +11 -6
- package/types/schemaoptions.d.ts +1 -2
- package/CHANGELOG.md +0 -7238
- package/History.md +0 -1
- package/lib/helpers/query/applyGlobalMaxTimeMS.js +0 -15
package/lib/model.js
CHANGED
|
@@ -1067,13 +1067,33 @@ Model.prototype.$__deleteOne = Model.prototype.$__remove;
|
|
|
1067
1067
|
* doc.model('User').findById(id, callback);
|
|
1068
1068
|
*
|
|
1069
1069
|
* @param {String} name model name
|
|
1070
|
+
* @method model
|
|
1070
1071
|
* @api public
|
|
1072
|
+
* @return {Model}
|
|
1071
1073
|
*/
|
|
1072
1074
|
|
|
1073
1075
|
Model.prototype.model = function model(name) {
|
|
1074
1076
|
return this[modelDbSymbol].model(name);
|
|
1075
1077
|
};
|
|
1076
1078
|
|
|
1079
|
+
/**
|
|
1080
|
+
* Returns another Model instance.
|
|
1081
|
+
*
|
|
1082
|
+
* #### Example:
|
|
1083
|
+
*
|
|
1084
|
+
* const doc = new Tank;
|
|
1085
|
+
* doc.model('User').findById(id, callback);
|
|
1086
|
+
*
|
|
1087
|
+
* @param {String} name model name
|
|
1088
|
+
* @method $model
|
|
1089
|
+
* @api public
|
|
1090
|
+
* @return {Model}
|
|
1091
|
+
*/
|
|
1092
|
+
|
|
1093
|
+
Model.prototype.$model = function $model(name) {
|
|
1094
|
+
return this[modelDbSymbol].model(name);
|
|
1095
|
+
};
|
|
1096
|
+
|
|
1077
1097
|
/**
|
|
1078
1098
|
* Returns a document with `_id` only if at least one document exists in the database that matches
|
|
1079
1099
|
* the given `filter`, and `null` otherwise.
|
|
@@ -1362,23 +1382,27 @@ Model.createCollection = function createCollection(options, callback) {
|
|
|
1362
1382
|
}
|
|
1363
1383
|
|
|
1364
1384
|
const schemaCollation = this &&
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1385
|
+
this.schema &&
|
|
1386
|
+
this.schema.options &&
|
|
1387
|
+
this.schema.options.collation;
|
|
1368
1388
|
if (schemaCollation != null) {
|
|
1369
1389
|
options = Object.assign({ collation: schemaCollation }, options);
|
|
1370
1390
|
}
|
|
1371
1391
|
const capped = this &&
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
if (capped) {
|
|
1376
|
-
|
|
1392
|
+
this.schema &&
|
|
1393
|
+
this.schema.options &&
|
|
1394
|
+
this.schema.options.capped;
|
|
1395
|
+
if (capped != null) {
|
|
1396
|
+
if (typeof capped === 'number') {
|
|
1397
|
+
options = Object.assign({ capped: true, size: capped }, options);
|
|
1398
|
+
} else if (typeof capped === 'object') {
|
|
1399
|
+
options = Object.assign({ capped: true }, capped, options);
|
|
1400
|
+
}
|
|
1377
1401
|
}
|
|
1378
1402
|
const timeseries = this &&
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1403
|
+
this.schema &&
|
|
1404
|
+
this.schema.options &&
|
|
1405
|
+
this.schema.options.timeseries;
|
|
1382
1406
|
if (timeseries != null) {
|
|
1383
1407
|
options = Object.assign({ timeseries }, options);
|
|
1384
1408
|
if (options.expireAfterSeconds != null) {
|
|
@@ -2148,14 +2172,7 @@ Model.find = function find(conditions, projection, options, callback) {
|
|
|
2148
2172
|
|
|
2149
2173
|
const mq = new this.Query({}, {}, this, this.$__collection);
|
|
2150
2174
|
mq.select(projection);
|
|
2151
|
-
|
|
2152
2175
|
mq.setOptions(options);
|
|
2153
|
-
if (this.schema.discriminatorMapping &&
|
|
2154
|
-
this.schema.discriminatorMapping.isRoot &&
|
|
2155
|
-
mq.selectedInclusively()) {
|
|
2156
|
-
// Need to select discriminator key because original schema doesn't have it
|
|
2157
|
-
mq.select(this.schema.options.discriminatorKey);
|
|
2158
|
-
}
|
|
2159
2176
|
|
|
2160
2177
|
callback = this.$handleCallbackError(callback);
|
|
2161
2178
|
|
|
@@ -2261,11 +2278,6 @@ Model.findOne = function findOne(conditions, projection, options, callback) {
|
|
|
2261
2278
|
const mq = new this.Query({}, {}, this, this.$__collection);
|
|
2262
2279
|
mq.select(projection);
|
|
2263
2280
|
mq.setOptions(options);
|
|
2264
|
-
if (this.schema.discriminatorMapping &&
|
|
2265
|
-
this.schema.discriminatorMapping.isRoot &&
|
|
2266
|
-
mq.selectedInclusively()) {
|
|
2267
|
-
mq.select(this.schema.options.discriminatorKey);
|
|
2268
|
-
}
|
|
2269
2281
|
|
|
2270
2282
|
callback = this.$handleCallbackError(callback);
|
|
2271
2283
|
return mq.findOne(conditions, callback);
|
|
@@ -3488,6 +3500,7 @@ function _setIsNew(doc, val) {
|
|
|
3488
3500
|
const subdocs = doc.$getAllSubdocs();
|
|
3489
3501
|
for (const subdoc of subdocs) {
|
|
3490
3502
|
subdoc.$isNew = val;
|
|
3503
|
+
subdoc.$emit('isNew', val);
|
|
3491
3504
|
}
|
|
3492
3505
|
}
|
|
3493
3506
|
|
|
@@ -4212,7 +4225,6 @@ Model.aggregate = function aggregate(pipeline, options, callback) {
|
|
|
4212
4225
|
|
|
4213
4226
|
const aggregate = new Aggregate(pipeline || []);
|
|
4214
4227
|
aggregate.model(this);
|
|
4215
|
-
|
|
4216
4228
|
if (options != null) {
|
|
4217
4229
|
aggregate.option(options);
|
|
4218
4230
|
}
|
|
@@ -4247,7 +4259,7 @@ Model.aggregate = function aggregate(pipeline, options, callback) {
|
|
|
4247
4259
|
* }
|
|
4248
4260
|
*
|
|
4249
4261
|
* @param {Object} obj
|
|
4250
|
-
* @param {Array} pathsToValidate
|
|
4262
|
+
* @param {Array|String} pathsToValidate
|
|
4251
4263
|
* @param {Object} [context]
|
|
4252
4264
|
* @param {Function} [callback]
|
|
4253
4265
|
* @return {Promise|undefined}
|
|
@@ -4266,7 +4278,7 @@ Model.validate = function validate(obj, pathsToValidate, context, callback) {
|
|
|
4266
4278
|
let paths = Object.keys(schema.paths);
|
|
4267
4279
|
|
|
4268
4280
|
if (pathsToValidate != null) {
|
|
4269
|
-
const _pathsToValidate = new Set(pathsToValidate);
|
|
4281
|
+
const _pathsToValidate = typeof pathsToValidate === 'string' ? new Set(pathsToValidate.split(' ')) : new Set(pathsToValidate);
|
|
4270
4282
|
paths = paths.filter(p => {
|
|
4271
4283
|
const pieces = p.split('.');
|
|
4272
4284
|
let cur = pieces[0];
|
|
@@ -4809,7 +4821,6 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4809
4821
|
o[schema.options.versionKey] = Number;
|
|
4810
4822
|
schema.add(o);
|
|
4811
4823
|
}
|
|
4812
|
-
|
|
4813
4824
|
let model;
|
|
4814
4825
|
if (typeof name === 'function' && name.prototype instanceof Model) {
|
|
4815
4826
|
model = name;
|
|
@@ -4853,6 +4864,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4853
4864
|
model.model = function model(name) {
|
|
4854
4865
|
return this.db.model(name);
|
|
4855
4866
|
};
|
|
4867
|
+
|
|
4856
4868
|
model.db = connection;
|
|
4857
4869
|
model.prototype.db = connection;
|
|
4858
4870
|
model.prototype[modelDbSymbol] = connection;
|
package/lib/query.js
CHANGED
|
@@ -12,7 +12,7 @@ const ObjectParameterError = require('./error/objectParameter');
|
|
|
12
12
|
const QueryCursor = require('./cursor/QueryCursor');
|
|
13
13
|
const ReadPreference = require('./driver').get().ReadPreference;
|
|
14
14
|
const ValidationError = require('./error/validation');
|
|
15
|
-
const applyGlobalMaxTimeMS = require('./helpers/query/
|
|
15
|
+
const { applyGlobalMaxTimeMS, applyGlobalDiskUse } = require('./helpers/query/applyGlobalOption');
|
|
16
16
|
const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
|
|
17
17
|
const cast = require('./cast');
|
|
18
18
|
const castArrayFilters = require('./helpers/update/castArrayFilters');
|
|
@@ -53,6 +53,7 @@ const queryOptionMethods = new Set([
|
|
|
53
53
|
'maxScan',
|
|
54
54
|
'maxTimeMS',
|
|
55
55
|
'maxscan',
|
|
56
|
+
'populate',
|
|
56
57
|
'projection',
|
|
57
58
|
'read',
|
|
58
59
|
'select',
|
|
@@ -2192,6 +2193,7 @@ function _castArrayFilters(query) {
|
|
|
2192
2193
|
* @api private
|
|
2193
2194
|
*/
|
|
2194
2195
|
Query.prototype._find = wrapThunk(function(callback) {
|
|
2196
|
+
|
|
2195
2197
|
this._castConditions();
|
|
2196
2198
|
|
|
2197
2199
|
if (this.error() != null) {
|
|
@@ -2210,6 +2212,7 @@ Query.prototype._find = wrapThunk(function(callback) {
|
|
|
2210
2212
|
const userProvidedFields = _this._userProvidedFields || {};
|
|
2211
2213
|
|
|
2212
2214
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2215
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2213
2216
|
|
|
2214
2217
|
// Separate options to pass down to `completeMany()` in case we need to
|
|
2215
2218
|
// set a session on the document
|
|
@@ -2228,8 +2231,15 @@ Query.prototype._find = wrapThunk(function(callback) {
|
|
|
2228
2231
|
if (this.options.explain) {
|
|
2229
2232
|
return callback(null, docs);
|
|
2230
2233
|
}
|
|
2231
|
-
|
|
2232
2234
|
if (!mongooseOptions.populate) {
|
|
2235
|
+
const versionKey = _this.schema.options.versionKey;
|
|
2236
|
+
if (mongooseOptions.lean && mongooseOptions.lean.versionKey === false && versionKey) {
|
|
2237
|
+
docs.forEach((doc) => {
|
|
2238
|
+
if (versionKey in doc) {
|
|
2239
|
+
delete doc[versionKey];
|
|
2240
|
+
}
|
|
2241
|
+
});
|
|
2242
|
+
}
|
|
2233
2243
|
return mongooseOptions.lean ?
|
|
2234
2244
|
callback(null, docs) :
|
|
2235
2245
|
completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions, callback);
|
|
@@ -2411,6 +2421,12 @@ Query.prototype._completeOne = function(doc, res, callback) {
|
|
|
2411
2421
|
}
|
|
2412
2422
|
|
|
2413
2423
|
if (!mongooseOptions.populate) {
|
|
2424
|
+
const versionKey = this.schema.options.versionKey;
|
|
2425
|
+
if (mongooseOptions.lean && mongooseOptions.lean.versionKey === false && versionKey) {
|
|
2426
|
+
if (versionKey in doc) {
|
|
2427
|
+
delete doc[versionKey];
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2414
2430
|
return mongooseOptions.lean ?
|
|
2415
2431
|
_completeOneLean(doc, res, options, callback) :
|
|
2416
2432
|
completeOne(model, doc, res, options, projection, userProvidedFields,
|
|
@@ -2453,8 +2469,8 @@ Query.prototype._findOne = wrapThunk(function(callback) {
|
|
|
2453
2469
|
|
|
2454
2470
|
this._applyPaths();
|
|
2455
2471
|
this._fields = this._castFields(this._fields);
|
|
2456
|
-
|
|
2457
2472
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2473
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2458
2474
|
|
|
2459
2475
|
// don't pass in the conditions because we already merged them in
|
|
2460
2476
|
Query.base.findOne.call(this, {}, (err, doc) => {
|
|
@@ -2567,6 +2583,7 @@ Query.prototype._count = wrapThunk(function(callback) {
|
|
|
2567
2583
|
}
|
|
2568
2584
|
|
|
2569
2585
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2586
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2570
2587
|
|
|
2571
2588
|
const conds = this._conditions;
|
|
2572
2589
|
const options = this._optionsForExec();
|
|
@@ -2594,6 +2611,7 @@ Query.prototype._countDocuments = wrapThunk(function(callback) {
|
|
|
2594
2611
|
}
|
|
2595
2612
|
|
|
2596
2613
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2614
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2597
2615
|
|
|
2598
2616
|
const conds = this._conditions;
|
|
2599
2617
|
const options = this._optionsForExec();
|
|
@@ -2814,6 +2832,7 @@ Query.prototype.__distinct = wrapThunk(function __distinct(callback) {
|
|
|
2814
2832
|
}
|
|
2815
2833
|
|
|
2816
2834
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2835
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2817
2836
|
|
|
2818
2837
|
const options = this._optionsForExec();
|
|
2819
2838
|
|
|
@@ -5739,4 +5758,4 @@ Query.prototype.model;
|
|
|
5739
5758
|
* Export
|
|
5740
5759
|
*/
|
|
5741
5760
|
|
|
5742
|
-
module.exports = Query;
|
|
5761
|
+
module.exports = Query;
|
package/lib/queryhelpers.js
CHANGED
|
@@ -261,7 +261,17 @@ exports.applyPaths = function applyPaths(fields, schema) {
|
|
|
261
261
|
delete fields[plusPath];
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
if (typeof type.selected !== 'boolean')
|
|
264
|
+
if (typeof type.selected !== 'boolean') {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// If set to 0, we're explicitly excluding the discriminator key. Can't do this for all fields,
|
|
269
|
+
// because we have tests that assert that using `-path` to exclude schema-level `select: true`
|
|
270
|
+
// fields counts as an exclusive projection. See gh-11546
|
|
271
|
+
if (exclude && type.selected && path === schema.options.discriminatorKey && fields[path] != null && !fields[path]) {
|
|
272
|
+
delete fields[path];
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
265
275
|
|
|
266
276
|
if (hasPlusPath) {
|
|
267
277
|
// forced inclusion
|
|
@@ -60,25 +60,13 @@ function _createConstructor(schema, baseClass) {
|
|
|
60
60
|
Subdocument || (Subdocument = require('../types/subdocument'));
|
|
61
61
|
|
|
62
62
|
const _embedded = function SingleNested(value, path, parent) {
|
|
63
|
-
const _this = this;
|
|
64
|
-
|
|
65
63
|
this.$__parent = parent;
|
|
66
64
|
Subdocument.apply(this, arguments);
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (parent) {
|
|
71
|
-
parent.$on('save', function() {
|
|
72
|
-
_this.emit('save', _this);
|
|
73
|
-
_this.constructor.emit('save', _this);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
parent.$on('isNew', function(val) {
|
|
77
|
-
_this.isNew = val;
|
|
78
|
-
_this.emit('isNew', val);
|
|
79
|
-
_this.constructor.emit('isNew', val);
|
|
80
|
-
});
|
|
66
|
+
if (parent == null) {
|
|
67
|
+
return;
|
|
81
68
|
}
|
|
69
|
+
this.$session(parent.$session());
|
|
82
70
|
};
|
|
83
71
|
|
|
84
72
|
schema._preCompile();
|
|
@@ -13,7 +13,6 @@ const SchemaType = require('../schematype');
|
|
|
13
13
|
const discriminator = require('../helpers/model/discriminator');
|
|
14
14
|
const handleIdOption = require('../helpers/schema/handleIdOption');
|
|
15
15
|
const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
|
|
16
|
-
const util = require('util');
|
|
17
16
|
const utils = require('../utils');
|
|
18
17
|
const getConstructor = require('../helpers/discriminator/getConstructor');
|
|
19
18
|
|
|
@@ -114,10 +113,12 @@ function _createConstructor(schema, options, baseClass) {
|
|
|
114
113
|
Subdocument || (Subdocument = require('../types/ArraySubdocument'));
|
|
115
114
|
|
|
116
115
|
// compile an embedded document for this schema
|
|
117
|
-
function EmbeddedDocument() {
|
|
116
|
+
function EmbeddedDocument(_value, parentArray) {
|
|
118
117
|
Subdocument.apply(this, arguments);
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
if (parentArray == null || parentArray.getArrayParent() == null) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.$session(parentArray.getArrayParent().$session());
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
schema._preCompile();
|
|
@@ -394,7 +395,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
394
395
|
|
|
395
396
|
if (!Array.isArray(value)) {
|
|
396
397
|
if (!init && !DocumentArrayPath.options.castNonArrays) {
|
|
397
|
-
throw new CastError('DocumentArray',
|
|
398
|
+
throw new CastError('DocumentArray', value, this.path, null, this);
|
|
398
399
|
}
|
|
399
400
|
// gh-2442 mark whole array as modified if we're initializing a doc from
|
|
400
401
|
// the db and the path isn't an array in the document
|
|
@@ -486,8 +487,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
486
487
|
// see gh-746
|
|
487
488
|
rawArray[i] = subdoc;
|
|
488
489
|
} catch (error) {
|
|
489
|
-
|
|
490
|
-
throw new CastError('embedded', valueInErrorMessage,
|
|
490
|
+
throw new CastError('embedded', rawArray[i],
|
|
491
491
|
value[arrayPathSymbol], error, this);
|
|
492
492
|
}
|
|
493
493
|
}
|
package/lib/schema/number.js
CHANGED
|
@@ -353,11 +353,7 @@ SchemaNumber.prototype.enum = function(values, message) {
|
|
|
353
353
|
*/
|
|
354
354
|
|
|
355
355
|
SchemaNumber.prototype.cast = function(value, doc, init) {
|
|
356
|
-
if (SchemaType._isRef(this, value, doc, init)) {
|
|
357
|
-
if (typeof value === 'number') {
|
|
358
|
-
return value;
|
|
359
|
-
}
|
|
360
|
-
|
|
356
|
+
if (typeof value !== 'number' && SchemaType._isRef(this, value, doc, init)) {
|
|
361
357
|
if (value == null || utils.isNonBuiltinObject(value)) {
|
|
362
358
|
return this._castRef(value, doc, init);
|
|
363
359
|
}
|
package/lib/schema/objectid.js
CHANGED
|
@@ -221,11 +221,9 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
221
221
|
*/
|
|
222
222
|
|
|
223
223
|
ObjectId.prototype.cast = function(value, doc, init) {
|
|
224
|
-
if (SchemaType._isRef(this, value, doc, init)) {
|
|
224
|
+
if (!(value instanceof oid) && SchemaType._isRef(this, value, doc, init)) {
|
|
225
225
|
// wait! we may need to cast this to a document
|
|
226
|
-
if (value
|
|
227
|
-
return value;
|
|
228
|
-
} else if ((getConstructorName(value) || '').toLowerCase() === 'objectid') {
|
|
226
|
+
if ((getConstructorName(value) || '').toLowerCase() === 'objectid') {
|
|
229
227
|
return new oid(value.toHexString());
|
|
230
228
|
}
|
|
231
229
|
|
package/lib/schema/string.js
CHANGED
|
@@ -580,11 +580,7 @@ SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
580
580
|
*/
|
|
581
581
|
|
|
582
582
|
SchemaString.prototype.cast = function(value, doc, init) {
|
|
583
|
-
if (SchemaType._isRef(this, value, doc, init)) {
|
|
584
|
-
if (typeof value === 'string') {
|
|
585
|
-
return value;
|
|
586
|
-
}
|
|
587
|
-
|
|
583
|
+
if (typeof value !== 'string' && SchemaType._isRef(this, value, doc, init)) {
|
|
588
584
|
return this._castRef(value, doc, init);
|
|
589
585
|
}
|
|
590
586
|
|
package/lib/schema.js
CHANGED
|
@@ -22,6 +22,7 @@ const readPref = require('./driver').get().ReadPreference;
|
|
|
22
22
|
const setupTimestamps = require('./helpers/timestamps/setupTimestamps');
|
|
23
23
|
const utils = require('./utils');
|
|
24
24
|
const validateRef = require('./helpers/populate/validateRef');
|
|
25
|
+
const util = require('util');
|
|
25
26
|
|
|
26
27
|
let MongooseTypes;
|
|
27
28
|
|
|
@@ -53,7 +54,7 @@ let id = 0;
|
|
|
53
54
|
* - [autoCreate](/docs/guide.html#autoCreate): bool - defaults to null (which means use the connection's autoCreate option)
|
|
54
55
|
* - [bufferCommands](/docs/guide.html#bufferCommands): bool - defaults to true
|
|
55
56
|
* - [bufferTimeoutMS](/docs/guide.html#bufferTimeoutMS): number - defaults to 10000 (10 seconds). If `bufferCommands` is enabled, the amount of time Mongoose will wait for connectivity to be restablished before erroring out.
|
|
56
|
-
* - [capped](/docs/guide.html#capped): bool - defaults to false
|
|
57
|
+
* - [capped](/docs/guide.html#capped): bool | number | object - defaults to false
|
|
57
58
|
* - [collection](/docs/guide.html#collection): string - no default
|
|
58
59
|
* - [discriminatorKey](/docs/guide.html#discriminatorKey): string - defaults to `__t`
|
|
59
60
|
* - [id](/docs/guide.html#id): bool - defaults to true
|
|
@@ -370,6 +371,9 @@ Schema.prototype._clone = function _clone(Constructor) {
|
|
|
370
371
|
if (this.discriminators != null) {
|
|
371
372
|
s.discriminators = Object.assign({}, this.discriminators);
|
|
372
373
|
}
|
|
374
|
+
if (this._applyDiscriminators != null) {
|
|
375
|
+
s._applyDiscriminators = Object.assign({}, this._applyDiscriminators);
|
|
376
|
+
}
|
|
373
377
|
|
|
374
378
|
s.aliases = Object.assign({}, this.aliases);
|
|
375
379
|
|
|
@@ -469,6 +473,11 @@ Schema.prototype.defaultOptions = function(options) {
|
|
|
469
473
|
return options;
|
|
470
474
|
};
|
|
471
475
|
|
|
476
|
+
Schema.prototype.discriminator = function(name, schema) {
|
|
477
|
+
this._applyDiscriminators = {};
|
|
478
|
+
this._applyDiscriminators[name] = schema;
|
|
479
|
+
};
|
|
480
|
+
|
|
472
481
|
/**
|
|
473
482
|
* Adds key path / schema type pairs to this schema.
|
|
474
483
|
*
|
|
@@ -510,7 +519,6 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
510
519
|
|
|
511
520
|
const keys = Object.keys(obj);
|
|
512
521
|
const typeKey = this.options.typeKey;
|
|
513
|
-
|
|
514
522
|
for (const key of keys) {
|
|
515
523
|
const fullPath = prefix + key;
|
|
516
524
|
const val = obj[key];
|
|
@@ -540,6 +548,25 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
540
548
|
this.nested[prefix.substring(0, prefix.length - 1)] = true;
|
|
541
549
|
}
|
|
542
550
|
this.path(prefix + key, val);
|
|
551
|
+
if (val[0] != null && !(val[0].instanceOfSchema) && utils.isPOJO(val[0].discriminators)) {
|
|
552
|
+
const schemaType = this.path(prefix + key);
|
|
553
|
+
for (const key in val[0].discriminators) {
|
|
554
|
+
schemaType.discriminator(key, val[0].discriminators[key]);
|
|
555
|
+
}
|
|
556
|
+
} else if (val[0] != null && val[0].instanceOfSchema && utils.isPOJO(val[0]._applyDiscriminators)) {
|
|
557
|
+
const applyDiscriminators = val[0]._applyDiscriminators || [];
|
|
558
|
+
const schemaType = this.path(prefix + key);
|
|
559
|
+
for (const disc in applyDiscriminators) {
|
|
560
|
+
schemaType.discriminator(disc, applyDiscriminators[disc]);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
else if (val != null && val.instanceOfSchema && utils.isPOJO(val._applyDiscriminators)) {
|
|
564
|
+
const applyDiscriminators = val._applyDiscriminators || [];
|
|
565
|
+
const schemaType = this.path(prefix + key);
|
|
566
|
+
for (const disc in applyDiscriminators) {
|
|
567
|
+
schemaType.discriminator(disc, applyDiscriminators[disc]);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
543
570
|
} else if (Object.keys(val).length < 1) {
|
|
544
571
|
// Special-case: {} always interpreted as Mixed path so leaf at this node
|
|
545
572
|
if (prefix) {
|
|
@@ -569,6 +596,12 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
569
596
|
this.nested[prefix.substring(0, prefix.length - 1)] = true;
|
|
570
597
|
}
|
|
571
598
|
this.path(prefix + key, val);
|
|
599
|
+
if (val != null && !(val.instanceOfSchema) && utils.isPOJO(val.discriminators)) {
|
|
600
|
+
const schemaType = this.path(prefix + key);
|
|
601
|
+
for (const key in val.discriminators) {
|
|
602
|
+
schemaType.discriminator(key, val.discriminators[key]);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
572
605
|
}
|
|
573
606
|
}
|
|
574
607
|
}
|
|
@@ -579,6 +612,86 @@ Schema.prototype.add = function add(obj, prefix) {
|
|
|
579
612
|
return this;
|
|
580
613
|
};
|
|
581
614
|
|
|
615
|
+
/**
|
|
616
|
+
* Remove an index by name or index specification.
|
|
617
|
+
*
|
|
618
|
+
* removeIndex only removes indexes from your schema object. Does **not** affect the indexes
|
|
619
|
+
* in MongoDB.
|
|
620
|
+
*
|
|
621
|
+
* ####Example:
|
|
622
|
+
*
|
|
623
|
+
* const ToySchema = new Schema({ name: String, color: String, price: Number });
|
|
624
|
+
*
|
|
625
|
+
* // Add a new index on { name, color }
|
|
626
|
+
* ToySchema.index({ name: 1, color: 1 });
|
|
627
|
+
*
|
|
628
|
+
* // Remove index on { name, color }
|
|
629
|
+
* // Keep in mind that order matters! `removeIndex({ color: 1, name: 1 })` won't remove the index
|
|
630
|
+
* ToySchema.removeIndex({ name: 1, color: 1 });
|
|
631
|
+
*
|
|
632
|
+
* // Add an index with a custom name
|
|
633
|
+
* ToySchema.index({ color: 1 }, { name: 'my custom index name' });
|
|
634
|
+
* // Remove index by name
|
|
635
|
+
* ToySchema.removeIndex('my custom index name');
|
|
636
|
+
*
|
|
637
|
+
* @param {Object|string} index name or index specification
|
|
638
|
+
* @return {Schema} the Schema instance
|
|
639
|
+
* @api public
|
|
640
|
+
*/
|
|
641
|
+
|
|
642
|
+
Schema.prototype.removeIndex = function removeIndex(index) {
|
|
643
|
+
if (arguments.length > 1) {
|
|
644
|
+
throw new Error('removeIndex() takes only 1 argument');
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (typeof index !== 'object' && typeof index !== 'string') {
|
|
648
|
+
throw new Error('removeIndex() may only take either an object or a string as an argument');
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (typeof index === 'object') {
|
|
652
|
+
for (let i = this._indexes.length - 1; i >= 0; --i) {
|
|
653
|
+
if (util.isDeepStrictEqual(this._indexes[i][0], index)) {
|
|
654
|
+
this._indexes.splice(i, 1);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
} else {
|
|
658
|
+
for (let i = this._indexes.length - 1; i >= 0; --i) {
|
|
659
|
+
if (this._indexes[i][1] != null && this._indexes[i][1].name === index) {
|
|
660
|
+
this._indexes.splice(i, 1);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return this;
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Remove all indexes from this schema.
|
|
670
|
+
*
|
|
671
|
+
* clearIndexes only removes indexes from your schema object. Does **not** affect the indexes
|
|
672
|
+
* in MongoDB.
|
|
673
|
+
*
|
|
674
|
+
* ####Example:
|
|
675
|
+
*
|
|
676
|
+
* const ToySchema = new Schema({ name: String, color: String, price: Number });
|
|
677
|
+
* ToySchema.index({ name: 1 });
|
|
678
|
+
* ToySchema.index({ color: 1 });
|
|
679
|
+
*
|
|
680
|
+
* // Remove all indexes on this schema
|
|
681
|
+
* ToySchema.clearIndexes();
|
|
682
|
+
*
|
|
683
|
+
* ToySchema.indexes(); // []
|
|
684
|
+
*
|
|
685
|
+
* @return {Schema} the Schema instance
|
|
686
|
+
* @api public
|
|
687
|
+
*/
|
|
688
|
+
|
|
689
|
+
Schema.prototype.clearIndexes = function clearIndexes() {
|
|
690
|
+
this._indexes.length = 0;
|
|
691
|
+
|
|
692
|
+
return this;
|
|
693
|
+
};
|
|
694
|
+
|
|
582
695
|
/**
|
|
583
696
|
* Reserved document keys.
|
|
584
697
|
*
|
package/lib/schematype.js
CHANGED
|
@@ -1148,7 +1148,7 @@ SchemaType.prototype.getDefault = function(scope, init) {
|
|
|
1148
1148
|
* @api private
|
|
1149
1149
|
*/
|
|
1150
1150
|
|
|
1151
|
-
SchemaType.prototype._applySetters = function(value, scope, init, priorVal) {
|
|
1151
|
+
SchemaType.prototype._applySetters = function(value, scope, init, priorVal, options) {
|
|
1152
1152
|
let v = value;
|
|
1153
1153
|
if (init) {
|
|
1154
1154
|
return v;
|
|
@@ -1156,7 +1156,7 @@ SchemaType.prototype._applySetters = function(value, scope, init, priorVal) {
|
|
|
1156
1156
|
const setters = this.setters;
|
|
1157
1157
|
|
|
1158
1158
|
for (let i = setters.length - 1; i >= 0; i--) {
|
|
1159
|
-
v = setters[i].call(scope, v, priorVal, this);
|
|
1159
|
+
v = setters[i].call(scope, v, priorVal, this, options);
|
|
1160
1160
|
}
|
|
1161
1161
|
|
|
1162
1162
|
return v;
|
|
@@ -22,6 +22,14 @@ const methods = {
|
|
|
22
22
|
return this.toObject(internalToObjectOptions);
|
|
23
23
|
},
|
|
24
24
|
|
|
25
|
+
/*!
|
|
26
|
+
* ignore
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
getArrayParent() {
|
|
30
|
+
return this[arrayParentSymbol];
|
|
31
|
+
},
|
|
32
|
+
|
|
25
33
|
/**
|
|
26
34
|
* Overrides MongooseArray#cast
|
|
27
35
|
*
|
|
@@ -311,8 +319,8 @@ const methods = {
|
|
|
311
319
|
return this;
|
|
312
320
|
}
|
|
313
321
|
const value = methods._cast.call(this, val, i);
|
|
314
|
-
arr[i] = value;
|
|
315
322
|
methods._markModified.call(this, i);
|
|
323
|
+
arr[i] = value;
|
|
316
324
|
return this;
|
|
317
325
|
},
|
|
318
326
|
|
|
@@ -414,9 +414,9 @@ const methods = {
|
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
if (!found) {
|
|
417
|
+
this._markModified();
|
|
417
418
|
rawArray.push(v);
|
|
418
419
|
this._registerAtomic('$addToSet', v);
|
|
419
|
-
this._markModified();
|
|
420
420
|
[].push.call(added, v);
|
|
421
421
|
}
|
|
422
422
|
}, this);
|
|
@@ -510,9 +510,9 @@ const methods = {
|
|
|
510
510
|
|
|
511
511
|
nonAtomicPush() {
|
|
512
512
|
const values = [].map.call(arguments, this._mapCast, this);
|
|
513
|
+
this._markModified();
|
|
513
514
|
const ret = [].push.apply(this, values);
|
|
514
515
|
this._registerAtomic('$set', this);
|
|
515
|
-
this._markModified();
|
|
516
516
|
return ret;
|
|
517
517
|
},
|
|
518
518
|
|
|
@@ -530,9 +530,9 @@ const methods = {
|
|
|
530
530
|
*/
|
|
531
531
|
|
|
532
532
|
pop() {
|
|
533
|
+
this._markModified();
|
|
533
534
|
const ret = [].pop.call(this);
|
|
534
535
|
this._registerAtomic('$set', this);
|
|
535
|
-
this._markModified();
|
|
536
536
|
return ret;
|
|
537
537
|
},
|
|
538
538
|
|
|
@@ -572,6 +572,7 @@ const methods = {
|
|
|
572
572
|
const cur = this[arrayParentSymbol].get(this[arrayPathSymbol]);
|
|
573
573
|
let i = cur.length;
|
|
574
574
|
let mem;
|
|
575
|
+
this._markModified();
|
|
575
576
|
|
|
576
577
|
while (i--) {
|
|
577
578
|
mem = cur[i];
|
|
@@ -595,7 +596,6 @@ const methods = {
|
|
|
595
596
|
this._registerAtomic('$pullAll', values);
|
|
596
597
|
}
|
|
597
598
|
|
|
598
|
-
this._markModified();
|
|
599
599
|
|
|
600
600
|
// Might have modified child paths and then pulled, like
|
|
601
601
|
// `doc.children[1].name = 'test';` followed by
|
|
@@ -657,7 +657,7 @@ const methods = {
|
|
|
657
657
|
undefined, { skipDocumentArrayCast: true });
|
|
658
658
|
let ret;
|
|
659
659
|
const atomics = this[arrayAtomicsSymbol];
|
|
660
|
-
|
|
660
|
+
this._markModified();
|
|
661
661
|
if (isOverwrite) {
|
|
662
662
|
atomic.$each = values;
|
|
663
663
|
|
|
@@ -684,7 +684,6 @@ const methods = {
|
|
|
684
684
|
}
|
|
685
685
|
|
|
686
686
|
this._registerAtomic('$push', atomic);
|
|
687
|
-
this._markModified();
|
|
688
687
|
return ret;
|
|
689
688
|
},
|
|
690
689
|
|
|
@@ -737,8 +736,8 @@ const methods = {
|
|
|
737
736
|
return this;
|
|
738
737
|
}
|
|
739
738
|
const value = methods._cast.call(this, val, i);
|
|
740
|
-
arr[i] = value;
|
|
741
739
|
methods._markModified.call(this, i);
|
|
740
|
+
arr[i] = value;
|
|
742
741
|
return this;
|
|
743
742
|
},
|
|
744
743
|
|
|
@@ -763,9 +762,9 @@ const methods = {
|
|
|
763
762
|
|
|
764
763
|
shift() {
|
|
765
764
|
const arr = utils.isMongooseArray(this) ? this.__array : this;
|
|
765
|
+
this._markModified();
|
|
766
766
|
const ret = [].shift.call(arr);
|
|
767
767
|
this._registerAtomic('$set', this);
|
|
768
|
-
this._markModified();
|
|
769
768
|
return ret;
|
|
770
769
|
},
|
|
771
770
|
|
|
@@ -890,9 +889,9 @@ const methods = {
|
|
|
890
889
|
}
|
|
891
890
|
|
|
892
891
|
const arr = utils.isMongooseArray(this) ? this.__array : this;
|
|
892
|
+
this._markModified();
|
|
893
893
|
[].unshift.apply(arr, values);
|
|
894
894
|
this._registerAtomic('$set', this);
|
|
895
|
-
this._markModified();
|
|
896
895
|
return this.length;
|
|
897
896
|
}
|
|
898
897
|
};
|