mongoose 6.2.10 → 6.3.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/.eslintrc.json +157 -157
- package/dist/browser.umd.js +2 -1693
- package/lib/aggregate.js +23 -31
- package/lib/collection.js +0 -7
- package/lib/cursor/ChangeStream.js +42 -2
- package/lib/cursor/QueryCursor.js +2 -0
- package/lib/document.js +13 -19
- package/lib/error/cast.js +7 -2
- package/lib/error/eachAsyncMultiError.js +41 -0
- package/lib/helpers/cursor/eachAsync.js +44 -12
- package/lib/helpers/indexes/applySchemaCollation.js +13 -0
- package/lib/helpers/indexes/isTextIndex.js +16 -0
- 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/query/castUpdate.js +3 -1
- package/lib/helpers/schematype/handleImmutable.js +4 -1
- package/lib/helpers/timestamps/setupTimestamps.js +2 -2
- package/lib/helpers/update/applyTimestampsToChildren.js +2 -2
- package/lib/helpers/update/applyTimestampsToUpdate.js +0 -1
- package/lib/index.js +11 -4
- package/lib/model.js +36 -36
- package/lib/query.js +59 -26
- package/lib/queryhelpers.js +11 -1
- package/lib/schema/SubdocumentPath.js +2 -1
- package/lib/schema/documentarray.js +2 -4
- package/lib/schema/objectid.js +0 -3
- package/lib/schema/string.js +24 -2
- package/lib/schema.js +117 -3
- package/lib/schematype.js +2 -3
- package/lib/types/DocumentArray/methods/index.js +1 -1
- package/lib/types/array/methods/index.js +9 -10
- package/lib/types/subdocument.js +29 -0
- package/lib/validoptions.js +1 -0
- package/package.json +13 -7
- package/tools/repl.js +2 -1
- package/tsconfig.json +2 -1
- package/types/aggregate.d.ts +223 -0
- package/types/connection.d.ts +2 -2
- package/types/cursor.d.ts +10 -4
- package/types/document.d.ts +3 -3
- package/types/index.d.ts +200 -215
- package/types/mongooseoptions.d.ts +10 -4
- package/CHANGELOG.md +0 -7227
- package/History.md +0 -1
- package/lib/helpers/query/applyGlobalMaxTimeMS.js +0 -15
|
@@ -19,13 +19,16 @@ module.exports = function(schematype) {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
function createImmutableSetter(path, immutable) {
|
|
22
|
-
return function immutableSetter(v) {
|
|
22
|
+
return function immutableSetter(v, _priorVal, _doc, options) {
|
|
23
23
|
if (this == null || this.$__ == null) {
|
|
24
24
|
return v;
|
|
25
25
|
}
|
|
26
26
|
if (this.isNew) {
|
|
27
27
|
return v;
|
|
28
28
|
}
|
|
29
|
+
if (options && options.overwriteImmutable) {
|
|
30
|
+
return v;
|
|
31
|
+
}
|
|
29
32
|
|
|
30
33
|
const _immutable = typeof immutable === 'function' ?
|
|
31
34
|
immutable.call(this, this) :
|
|
@@ -48,8 +48,8 @@ module.exports = function setupTimestamps(schema, timestamps) {
|
|
|
48
48
|
currentTime() :
|
|
49
49
|
this.ownerDocument().constructor.base.now();
|
|
50
50
|
|
|
51
|
-
if (!skipCreatedAt && this.isNew && createdAt && !this.$__getValue(createdAt) && this.$__isSelected(createdAt)) {
|
|
52
|
-
this.$set(createdAt, defaultTimestamp);
|
|
51
|
+
if (!skipCreatedAt && (this.isNew || this.$isSubdocument) && createdAt && !this.$__getValue(createdAt) && this.$__isSelected(createdAt)) {
|
|
52
|
+
this.$set(createdAt, defaultTimestamp, undefined, { overwriteImmutable: true });
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
if (!skipUpdatedAt && updatedAt && (this.isNew || this.$isModified())) {
|
|
@@ -15,7 +15,7 @@ function applyTimestampsToChildren(now, update, schema) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const keys = Object.keys(update);
|
|
18
|
-
const hasDollarKey = keys.some(key => key
|
|
18
|
+
const hasDollarKey = keys.some(key => key[0] === '$');
|
|
19
19
|
|
|
20
20
|
if (hasDollarKey) {
|
|
21
21
|
if (update.$push) {
|
|
@@ -38,7 +38,7 @@ function applyTimestampsToChildren(now, update, schema) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const updateKeys = Object.keys(update).filter(key =>
|
|
41
|
+
const updateKeys = Object.keys(update).filter(key => key[0] !== '$');
|
|
42
42
|
for (const key of updateKeys) {
|
|
43
43
|
applyTimestampsToUpdateKey(schema, key, update, now);
|
|
44
44
|
}
|
package/lib/index.js
CHANGED
|
@@ -179,7 +179,9 @@ Mongoose.prototype.driver = driver;
|
|
|
179
179
|
Mongoose.prototype.set = function(key, value) {
|
|
180
180
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
181
181
|
|
|
182
|
-
if (VALID_OPTIONS.indexOf(key) === -1)
|
|
182
|
+
if (VALID_OPTIONS.indexOf(key) === -1) {
|
|
183
|
+
throw new Error(`\`${key}\` is an invalid option.`);
|
|
184
|
+
}
|
|
183
185
|
|
|
184
186
|
if (arguments.length === 1) {
|
|
185
187
|
return _mongoose.options[key];
|
|
@@ -265,7 +267,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
|
|
265
267
|
* @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
|
|
266
268
|
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
|
267
269
|
* @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.
|
|
268
|
-
* @return {Connection} the created Connection object. Connections are thenable, so you can
|
|
270
|
+
* @return {Connection} the created Connection object. Connections are not thenable, so you can not `await mongoose.createConnection()`. To await use mongoose.createConnection(uri).asPromise() instead.
|
|
269
271
|
* @api public
|
|
270
272
|
*/
|
|
271
273
|
|
|
@@ -467,6 +469,7 @@ Mongoose.prototype.pluralize = function(fn) {
|
|
|
467
469
|
*/
|
|
468
470
|
|
|
469
471
|
Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
472
|
+
|
|
470
473
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
471
474
|
|
|
472
475
|
if (typeof schema === 'string') {
|
|
@@ -519,7 +522,6 @@ Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
|
519
522
|
}
|
|
520
523
|
|
|
521
524
|
const model = _mongoose._model(name, schema, collection, options);
|
|
522
|
-
|
|
523
525
|
_mongoose.connection.models[name] = model;
|
|
524
526
|
_mongoose.models[name] = model;
|
|
525
527
|
|
|
@@ -561,12 +563,17 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
|
|
|
561
563
|
|
|
562
564
|
const connection = options.connection || _mongoose.connection;
|
|
563
565
|
model = _mongoose.Model.compile(model || name, schema, collection, connection, _mongoose);
|
|
564
|
-
|
|
565
566
|
// Errors handled internally, so safe to ignore error
|
|
566
567
|
model.init(function $modelInitNoop() {});
|
|
567
568
|
|
|
568
569
|
connection.emit('model', model);
|
|
569
570
|
|
|
571
|
+
if (schema._applyDiscriminators != null) {
|
|
572
|
+
for (const disc of Object.keys(schema._applyDiscriminators)) {
|
|
573
|
+
model.discriminator(disc, schema._applyDiscriminators[disc]);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
570
577
|
return model;
|
|
571
578
|
};
|
|
572
579
|
|
package/lib/model.js
CHANGED
|
@@ -26,6 +26,7 @@ const applyQueryMiddleware = require('./helpers/query/applyQueryMiddleware');
|
|
|
26
26
|
const applyHooks = require('./helpers/model/applyHooks');
|
|
27
27
|
const applyMethods = require('./helpers/model/applyMethods');
|
|
28
28
|
const applyProjection = require('./helpers/projection/applyProjection');
|
|
29
|
+
const applySchemaCollation = require('./helpers/indexes/applySchemaCollation');
|
|
29
30
|
const applyStaticHooks = require('./helpers/model/applyStaticHooks');
|
|
30
31
|
const applyStatics = require('./helpers/model/applyStatics');
|
|
31
32
|
const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
|
|
@@ -1073,6 +1074,22 @@ Model.prototype.model = function model(name) {
|
|
|
1073
1074
|
return this[modelDbSymbol].model(name);
|
|
1074
1075
|
};
|
|
1075
1076
|
|
|
1077
|
+
/**
|
|
1078
|
+
* Returns another Model instance.
|
|
1079
|
+
*
|
|
1080
|
+
* #### Example:
|
|
1081
|
+
*
|
|
1082
|
+
* const doc = new Tank;
|
|
1083
|
+
* doc.model('User').findById(id, callback);
|
|
1084
|
+
*
|
|
1085
|
+
* @param {String} name model name
|
|
1086
|
+
* @api public
|
|
1087
|
+
*/
|
|
1088
|
+
|
|
1089
|
+
Model.prototype.$model = function $model(name) {
|
|
1090
|
+
return this[modelDbSymbol].model(name);
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1076
1093
|
/**
|
|
1077
1094
|
* Returns a document with `_id` only if at least one document exists in the database that matches
|
|
1078
1095
|
* the given `filter`, and `null` otherwise.
|
|
@@ -1361,23 +1378,27 @@ Model.createCollection = function createCollection(options, callback) {
|
|
|
1361
1378
|
}
|
|
1362
1379
|
|
|
1363
1380
|
const schemaCollation = this &&
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1381
|
+
this.schema &&
|
|
1382
|
+
this.schema.options &&
|
|
1383
|
+
this.schema.options.collation;
|
|
1367
1384
|
if (schemaCollation != null) {
|
|
1368
1385
|
options = Object.assign({ collation: schemaCollation }, options);
|
|
1369
1386
|
}
|
|
1370
1387
|
const capped = this &&
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
if (capped) {
|
|
1375
|
-
|
|
1388
|
+
this.schema &&
|
|
1389
|
+
this.schema.options &&
|
|
1390
|
+
this.schema.options.capped;
|
|
1391
|
+
if (capped != null) {
|
|
1392
|
+
if (typeof capped === 'number') {
|
|
1393
|
+
options = Object.assign({ capped: true, size: capped }, options);
|
|
1394
|
+
} else if (typeof capped === 'object') {
|
|
1395
|
+
options = Object.assign({ capped: true }, capped, options);
|
|
1396
|
+
}
|
|
1376
1397
|
}
|
|
1377
1398
|
const timeseries = this &&
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1399
|
+
this.schema &&
|
|
1400
|
+
this.schema.options &&
|
|
1401
|
+
this.schema.options.timeseries;
|
|
1381
1402
|
if (timeseries != null) {
|
|
1382
1403
|
options = Object.assign({ timeseries }, options);
|
|
1383
1404
|
if (options.expireAfterSeconds != null) {
|
|
@@ -1562,6 +1583,7 @@ Model.cleanIndexes = function cleanIndexes(callback) {
|
|
|
1562
1583
|
|
|
1563
1584
|
for (const [schemaIndexKeysObject, schemaIndexOptions] of schemaIndexes) {
|
|
1564
1585
|
const options = decorateDiscriminatorIndexOptions(this.schema, utils.clone(schemaIndexOptions));
|
|
1586
|
+
applySchemaCollation(schemaIndexKeysObject, options, this.schema.options);
|
|
1565
1587
|
|
|
1566
1588
|
if (isIndexEqual(schemaIndexKeysObject, options, dbIndex)) {
|
|
1567
1589
|
found = true;
|
|
@@ -1780,26 +1802,17 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1780
1802
|
|
|
1781
1803
|
const indexFields = utils.clone(index[0]);
|
|
1782
1804
|
const indexOptions = utils.clone(index[1]);
|
|
1783
|
-
|
|
1784
|
-
for (const key of Object.keys(indexFields)) {
|
|
1785
|
-
if (indexFields[key] === 'text') {
|
|
1786
|
-
isTextIndex = true;
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1805
|
+
|
|
1789
1806
|
delete indexOptions._autoIndex;
|
|
1790
1807
|
decorateDiscriminatorIndexOptions(model.schema, indexOptions);
|
|
1791
1808
|
applyWriteConcern(model.schema, indexOptions);
|
|
1809
|
+
applySchemaCollation(indexFields, indexOptions, model.schema.options);
|
|
1792
1810
|
|
|
1793
1811
|
indexSingleStart(indexFields, options);
|
|
1794
1812
|
|
|
1795
1813
|
if ('background' in options) {
|
|
1796
1814
|
indexOptions.background = options.background;
|
|
1797
1815
|
}
|
|
1798
|
-
if (model.schema.options.hasOwnProperty('collation') &&
|
|
1799
|
-
!indexOptions.hasOwnProperty('collation') &&
|
|
1800
|
-
!isTextIndex) {
|
|
1801
|
-
indexOptions.collation = model.schema.options.collation;
|
|
1802
|
-
}
|
|
1803
1816
|
|
|
1804
1817
|
model.collection.createIndex(indexFields, indexOptions, utils.tick(function(err, name) {
|
|
1805
1818
|
indexSingleDone(err, indexFields, indexOptions, name);
|
|
@@ -2155,14 +2168,7 @@ Model.find = function find(conditions, projection, options, callback) {
|
|
|
2155
2168
|
|
|
2156
2169
|
const mq = new this.Query({}, {}, this, this.$__collection);
|
|
2157
2170
|
mq.select(projection);
|
|
2158
|
-
|
|
2159
2171
|
mq.setOptions(options);
|
|
2160
|
-
if (this.schema.discriminatorMapping &&
|
|
2161
|
-
this.schema.discriminatorMapping.isRoot &&
|
|
2162
|
-
mq.selectedInclusively()) {
|
|
2163
|
-
// Need to select discriminator key because original schema doesn't have it
|
|
2164
|
-
mq.select(this.schema.options.discriminatorKey);
|
|
2165
|
-
}
|
|
2166
2172
|
|
|
2167
2173
|
callback = this.$handleCallbackError(callback);
|
|
2168
2174
|
|
|
@@ -2268,11 +2274,6 @@ Model.findOne = function findOne(conditions, projection, options, callback) {
|
|
|
2268
2274
|
const mq = new this.Query({}, {}, this, this.$__collection);
|
|
2269
2275
|
mq.select(projection);
|
|
2270
2276
|
mq.setOptions(options);
|
|
2271
|
-
if (this.schema.discriminatorMapping &&
|
|
2272
|
-
this.schema.discriminatorMapping.isRoot &&
|
|
2273
|
-
mq.selectedInclusively()) {
|
|
2274
|
-
mq.select(this.schema.options.discriminatorKey);
|
|
2275
|
-
}
|
|
2276
2277
|
|
|
2277
2278
|
callback = this.$handleCallbackError(callback);
|
|
2278
2279
|
return mq.findOne(conditions, callback);
|
|
@@ -4219,7 +4220,6 @@ Model.aggregate = function aggregate(pipeline, options, callback) {
|
|
|
4219
4220
|
|
|
4220
4221
|
const aggregate = new Aggregate(pipeline || []);
|
|
4221
4222
|
aggregate.model(this);
|
|
4222
|
-
|
|
4223
4223
|
if (options != null) {
|
|
4224
4224
|
aggregate.option(options);
|
|
4225
4225
|
}
|
|
@@ -4816,7 +4816,6 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4816
4816
|
o[schema.options.versionKey] = Number;
|
|
4817
4817
|
schema.add(o);
|
|
4818
4818
|
}
|
|
4819
|
-
|
|
4820
4819
|
let model;
|
|
4821
4820
|
if (typeof name === 'function' && name.prototype instanceof Model) {
|
|
4822
4821
|
model = name;
|
|
@@ -4860,6 +4859,7 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
|
|
|
4860
4859
|
model.model = function model(name) {
|
|
4861
4860
|
return this.db.model(name);
|
|
4862
4861
|
};
|
|
4862
|
+
|
|
4863
4863
|
model.db = connection;
|
|
4864
4864
|
model.prototype.db = connection;
|
|
4865
4865
|
model.prototype[modelDbSymbol] = connection;
|
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
|
|
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');
|
|
@@ -2191,6 +2192,7 @@ function _castArrayFilters(query) {
|
|
|
2191
2192
|
* @api private
|
|
2192
2193
|
*/
|
|
2193
2194
|
Query.prototype._find = wrapThunk(function(callback) {
|
|
2195
|
+
|
|
2194
2196
|
this._castConditions();
|
|
2195
2197
|
|
|
2196
2198
|
if (this.error() != null) {
|
|
@@ -2209,6 +2211,7 @@ Query.prototype._find = wrapThunk(function(callback) {
|
|
|
2209
2211
|
const userProvidedFields = _this._userProvidedFields || {};
|
|
2210
2212
|
|
|
2211
2213
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2214
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2212
2215
|
|
|
2213
2216
|
// Separate options to pass down to `completeMany()` in case we need to
|
|
2214
2217
|
// set a session on the document
|
|
@@ -2227,8 +2230,15 @@ Query.prototype._find = wrapThunk(function(callback) {
|
|
|
2227
2230
|
if (this.options.explain) {
|
|
2228
2231
|
return callback(null, docs);
|
|
2229
2232
|
}
|
|
2230
|
-
|
|
2231
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
|
+
}
|
|
2232
2242
|
return mongooseOptions.lean ?
|
|
2233
2243
|
callback(null, docs) :
|
|
2234
2244
|
completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions, callback);
|
|
@@ -2410,6 +2420,12 @@ Query.prototype._completeOne = function(doc, res, callback) {
|
|
|
2410
2420
|
}
|
|
2411
2421
|
|
|
2412
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
|
+
}
|
|
2413
2429
|
return mongooseOptions.lean ?
|
|
2414
2430
|
_completeOneLean(doc, res, options, callback) :
|
|
2415
2431
|
completeOne(model, doc, res, options, projection, userProvidedFields,
|
|
@@ -2452,8 +2468,8 @@ Query.prototype._findOne = wrapThunk(function(callback) {
|
|
|
2452
2468
|
|
|
2453
2469
|
this._applyPaths();
|
|
2454
2470
|
this._fields = this._castFields(this._fields);
|
|
2455
|
-
|
|
2456
2471
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2472
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2457
2473
|
|
|
2458
2474
|
// don't pass in the conditions because we already merged them in
|
|
2459
2475
|
Query.base.findOne.call(this, {}, (err, doc) => {
|
|
@@ -2566,6 +2582,7 @@ Query.prototype._count = wrapThunk(function(callback) {
|
|
|
2566
2582
|
}
|
|
2567
2583
|
|
|
2568
2584
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2585
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2569
2586
|
|
|
2570
2587
|
const conds = this._conditions;
|
|
2571
2588
|
const options = this._optionsForExec();
|
|
@@ -2593,6 +2610,7 @@ Query.prototype._countDocuments = wrapThunk(function(callback) {
|
|
|
2593
2610
|
}
|
|
2594
2611
|
|
|
2595
2612
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2613
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2596
2614
|
|
|
2597
2615
|
const conds = this._conditions;
|
|
2598
2616
|
const options = this._optionsForExec();
|
|
@@ -2813,6 +2831,7 @@ Query.prototype.__distinct = wrapThunk(function __distinct(callback) {
|
|
|
2813
2831
|
}
|
|
2814
2832
|
|
|
2815
2833
|
applyGlobalMaxTimeMS(this.options, this.model);
|
|
2834
|
+
applyGlobalDiskUse(this.options, this.model);
|
|
2816
2835
|
|
|
2817
2836
|
const options = this._optionsForExec();
|
|
2818
2837
|
|
|
@@ -3713,7 +3732,6 @@ Query.prototype.findOneAndReplace = function(filter, replacement, options, callb
|
|
|
3713
3732
|
*/
|
|
3714
3733
|
Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
|
|
3715
3734
|
this._castConditions();
|
|
3716
|
-
|
|
3717
3735
|
if (this.error() != null) {
|
|
3718
3736
|
callback(this.error());
|
|
3719
3737
|
return null;
|
|
@@ -3724,9 +3742,6 @@ Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
|
|
|
3724
3742
|
convertNewToReturnDocument(options);
|
|
3725
3743
|
let fields = null;
|
|
3726
3744
|
|
|
3727
|
-
let castedDoc = new this.model(this._update, null, true);
|
|
3728
|
-
this._update = castedDoc;
|
|
3729
|
-
|
|
3730
3745
|
this._applyPaths();
|
|
3731
3746
|
if (this._fields != null) {
|
|
3732
3747
|
options.projection = this._castFields(utils.clone(this._fields));
|
|
@@ -3737,7 +3752,34 @@ Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
|
|
|
3737
3752
|
}
|
|
3738
3753
|
}
|
|
3739
3754
|
|
|
3740
|
-
|
|
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 => {
|
|
3741
3783
|
if (err != null) {
|
|
3742
3784
|
return callback(err);
|
|
3743
3785
|
}
|
|
@@ -3860,7 +3902,11 @@ Query.prototype._findAndModify = function(type, callback) {
|
|
|
3860
3902
|
}
|
|
3861
3903
|
|
|
3862
3904
|
if (!isOverwriting) {
|
|
3863
|
-
|
|
3905
|
+
try {
|
|
3906
|
+
this._update = this._castUpdate(this._update, opts.overwrite);
|
|
3907
|
+
} catch (err) {
|
|
3908
|
+
return callback(err);
|
|
3909
|
+
}
|
|
3864
3910
|
const _opts = Object.assign({}, opts, {
|
|
3865
3911
|
setDefaultsOnInsert: this._mongooseOptions.setDefaultsOnInsert
|
|
3866
3912
|
});
|
|
@@ -4055,10 +4101,10 @@ function _updateThunk(op, callback) {
|
|
|
4055
4101
|
}
|
|
4056
4102
|
this._update = new this.model(this._update, null, true);
|
|
4057
4103
|
} else {
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
callback(
|
|
4104
|
+
try {
|
|
4105
|
+
this._update = this._castUpdate(this._update, options.overwrite);
|
|
4106
|
+
} catch (err) {
|
|
4107
|
+
callback(err);
|
|
4062
4108
|
return null;
|
|
4063
4109
|
}
|
|
4064
4110
|
|
|
@@ -4897,19 +4943,6 @@ function castQuery(query) {
|
|
|
4897
4943
|
}
|
|
4898
4944
|
}
|
|
4899
4945
|
|
|
4900
|
-
/*!
|
|
4901
|
-
* castDoc
|
|
4902
|
-
* @api private
|
|
4903
|
-
*/
|
|
4904
|
-
|
|
4905
|
-
function castDoc(query, overwrite) {
|
|
4906
|
-
try {
|
|
4907
|
-
return query._castUpdate(query._update, overwrite);
|
|
4908
|
-
} catch (err) {
|
|
4909
|
-
return err;
|
|
4910
|
-
}
|
|
4911
|
-
}
|
|
4912
|
-
|
|
4913
4946
|
/**
|
|
4914
4947
|
* Specifies paths which should be populated with other documents.
|
|
4915
4948
|
*
|
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
|
|
@@ -167,10 +167,11 @@ SubdocumentPath.prototype.cast = function(val, doc, init, priorVal, options) {
|
|
|
167
167
|
const path = this.path;
|
|
168
168
|
const selected = Object.keys(parentSelected).reduce((obj, key) => {
|
|
169
169
|
if (key.startsWith(path + '.')) {
|
|
170
|
+
obj = obj || {};
|
|
170
171
|
obj[key.substring(path.length + 1)] = parentSelected[key];
|
|
171
172
|
}
|
|
172
173
|
return obj;
|
|
173
|
-
},
|
|
174
|
+
}, null);
|
|
174
175
|
options = Object.assign({}, options, { priorDoc: priorVal });
|
|
175
176
|
if (init) {
|
|
176
177
|
subdoc = new Constructor(void 0, selected, doc);
|
|
@@ -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
|
|
|
@@ -394,7 +393,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
394
393
|
|
|
395
394
|
if (!Array.isArray(value)) {
|
|
396
395
|
if (!init && !DocumentArrayPath.options.castNonArrays) {
|
|
397
|
-
throw new CastError('DocumentArray',
|
|
396
|
+
throw new CastError('DocumentArray', value, this.path, null, this);
|
|
398
397
|
}
|
|
399
398
|
// gh-2442 mark whole array as modified if we're initializing a doc from
|
|
400
399
|
// the db and the path isn't an array in the document
|
|
@@ -486,8 +485,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
486
485
|
// see gh-746
|
|
487
486
|
rawArray[i] = subdoc;
|
|
488
487
|
} catch (error) {
|
|
489
|
-
|
|
490
|
-
throw new CastError('embedded', valueInErrorMessage,
|
|
488
|
+
throw new CastError('embedded', rawArray[i],
|
|
491
489
|
value[arrayPathSymbol], error, this);
|
|
492
490
|
}
|
|
493
491
|
}
|
package/lib/schema/objectid.js
CHANGED
package/lib/schema/string.js
CHANGED
|
@@ -612,6 +612,10 @@ function handleSingle(val) {
|
|
|
612
612
|
return this.castForQuery(val);
|
|
613
613
|
}
|
|
614
614
|
|
|
615
|
+
/*!
|
|
616
|
+
* ignore
|
|
617
|
+
*/
|
|
618
|
+
|
|
615
619
|
function handleArray(val) {
|
|
616
620
|
const _this = this;
|
|
617
621
|
if (!Array.isArray(val)) {
|
|
@@ -622,14 +626,32 @@ function handleArray(val) {
|
|
|
622
626
|
});
|
|
623
627
|
}
|
|
624
628
|
|
|
629
|
+
/*!
|
|
630
|
+
* ignore
|
|
631
|
+
*/
|
|
632
|
+
|
|
633
|
+
function handleSingleNoSetters(val) {
|
|
634
|
+
if (val == null) {
|
|
635
|
+
return this._castNullish(val);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return this.cast(val, this);
|
|
639
|
+
}
|
|
640
|
+
|
|
625
641
|
const $conditionalHandlers = utils.options(SchemaType.prototype.$conditionalHandlers, {
|
|
626
642
|
$all: handleArray,
|
|
627
643
|
$gt: handleSingle,
|
|
628
644
|
$gte: handleSingle,
|
|
629
645
|
$lt: handleSingle,
|
|
630
646
|
$lte: handleSingle,
|
|
631
|
-
$options:
|
|
632
|
-
$regex:
|
|
647
|
+
$options: handleSingleNoSetters,
|
|
648
|
+
$regex: function handle$regex(val) {
|
|
649
|
+
if (Object.prototype.toString.call(val) === '[object RegExp]') {
|
|
650
|
+
return val;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
return handleSingleNoSetters.call(this, val);
|
|
654
|
+
},
|
|
633
655
|
$not: handleSingle
|
|
634
656
|
});
|
|
635
657
|
|