mongoose 9.0.1 → 9.1.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.
- package/lib/aggregate.js +1 -1
- package/lib/cast/string.js +1 -1
- package/lib/cast.js +7 -15
- package/lib/collection.js +2 -2
- package/lib/connection.js +20 -14
- package/lib/cursor/changeStream.js +5 -5
- package/lib/document.js +126 -79
- package/lib/drivers/node-mongodb-native/collection.js +33 -126
- package/lib/drivers/node-mongodb-native/connection.js +8 -23
- package/lib/error/cast.js +1 -1
- package/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +4 -4
- package/lib/helpers/clone.js +8 -8
- package/lib/helpers/common.js +4 -4
- package/lib/helpers/cursor/eachAsync.js +1 -1
- package/lib/helpers/discriminator/getConstructor.js +1 -1
- package/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +1 -1
- package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +2 -2
- package/lib/helpers/document/applyDefaults.js +1 -1
- package/lib/helpers/document/applyTimestamps.js +2 -1
- package/lib/helpers/document/applyVirtuals.js +4 -3
- package/lib/helpers/document/cleanModifiedSubpaths.js +1 -1
- package/lib/helpers/document/compile.js +4 -4
- package/lib/helpers/document/getDeepestSubdocumentForPath.js +1 -1
- package/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +1 -1
- package/lib/helpers/indexes/getRelatedIndexes.js +3 -3
- package/lib/helpers/model/castBulkWrite.js +5 -9
- package/lib/helpers/model/discriminator.js +1 -1
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -1
- package/lib/helpers/populate/assignVals.js +4 -4
- package/lib/helpers/populate/getModelsMapForPopulate.js +25 -23
- package/lib/helpers/populate/getSchemaTypes.js +6 -7
- package/lib/helpers/printJestWarning.js +1 -1
- package/lib/helpers/processConnectionOptions.js +1 -1
- package/lib/helpers/query/castUpdate.js +12 -12
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +2 -2
- package/lib/helpers/query/handleImmutable.js +2 -2
- package/lib/helpers/query/sanitizeFilter.js +1 -1
- package/lib/helpers/schema/applyPlugins.js +1 -1
- package/lib/helpers/schema/applyReadConcern.js +1 -1
- package/lib/helpers/schema/applyWriteConcern.js +4 -2
- package/lib/helpers/schema/getIndexes.js +3 -3
- package/lib/helpers/schema/getSubdocumentStrictValue.js +1 -1
- package/lib/helpers/schema/handleIdOption.js +1 -1
- package/lib/helpers/schema/idGetter.js +1 -1
- package/lib/helpers/schematype/handleImmutable.js +1 -1
- package/lib/helpers/setDefaultsOnInsert.js +2 -5
- package/lib/helpers/timestamps/setDocumentTimestamps.js +2 -2
- package/lib/helpers/timestamps/setupTimestamps.js +2 -2
- package/lib/helpers/update/applyTimestampsToUpdate.js +10 -9
- package/lib/helpers/update/castArrayFilters.js +4 -4
- package/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
- package/lib/helpers/updateValidators.js +4 -4
- package/lib/model.js +42 -48
- package/lib/mongoose.js +5 -5
- package/lib/options/virtualOptions.js +1 -1
- package/lib/plugins/saveSubdocs.js +2 -2
- package/lib/plugins/trackTransaction.js +3 -4
- package/lib/query.js +62 -59
- package/lib/queryHelpers.js +9 -12
- package/lib/schema/array.js +10 -12
- package/lib/schema/buffer.js +6 -6
- package/lib/schema/documentArray.js +15 -23
- package/lib/schema/documentArrayElement.js +3 -3
- package/lib/schema/map.js +1 -1
- package/lib/schema/mixed.js +2 -2
- package/lib/schema/number.js +22 -4
- package/lib/schema/objectId.js +1 -1
- package/lib/schema/operators/exists.js +1 -1
- package/lib/schema/operators/geospatial.js +1 -1
- package/lib/schema/string.js +2 -2
- package/lib/schema/subdocument.js +9 -12
- package/lib/schema/union.js +1 -1
- package/lib/schema.js +27 -28
- package/lib/schemaType.js +11 -11
- package/lib/types/array/index.js +2 -2
- package/lib/types/array/methods/index.js +38 -8
- package/lib/types/arraySubdocument.js +12 -2
- package/lib/types/buffer.js +1 -1
- package/lib/types/documentArray/index.js +2 -2
- package/lib/types/documentArray/methods/index.js +5 -5
- package/lib/types/map.js +8 -8
- package/lib/types/subdocument.js +15 -5
- package/lib/utils.js +23 -7
- package/package.json +3 -2
- package/types/index.d.ts +26 -9
- package/types/inferrawdoctype.d.ts +9 -3
- package/types/inferschematype.d.ts +20 -27
- package/types/middlewares.d.ts +11 -0
- package/types/models.d.ts +15 -5
- package/types/query.d.ts +1 -1
- package/types/schemaoptions.d.ts +4 -2
- package/types/utility.d.ts +1 -1
- package/types/virtuals.d.ts +3 -3
package/lib/query.js
CHANGED
|
@@ -136,7 +136,7 @@ function Query(conditions, options, model, collection) {
|
|
|
136
136
|
|
|
137
137
|
// this is needed because map reduce returns a model that can be queried, but
|
|
138
138
|
// all of the queries on said model should be lean
|
|
139
|
-
if (this.model
|
|
139
|
+
if (this.model?._mapreduce) {
|
|
140
140
|
this.lean();
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -156,10 +156,7 @@ function Query(conditions, options, model, collection) {
|
|
|
156
156
|
// versions of MongoDB
|
|
157
157
|
this.$useProjection = true;
|
|
158
158
|
|
|
159
|
-
const collation = this
|
|
160
|
-
this.schema &&
|
|
161
|
-
this.schema.options &&
|
|
162
|
-
this.schema.options.collation || null;
|
|
159
|
+
const collation = this?.schema?.options?.collation || null;
|
|
163
160
|
if (collation != null) {
|
|
164
161
|
this.options.collation = collation;
|
|
165
162
|
}
|
|
@@ -169,7 +166,7 @@ function Query(conditions, options, model, collection) {
|
|
|
169
166
|
function isEmptyFilter(obj) {
|
|
170
167
|
if (obj == null) return true;
|
|
171
168
|
if (typeof obj !== 'object') return true;
|
|
172
|
-
if (
|
|
169
|
+
if (utils.hasOwnKeys(obj) === false) return true;
|
|
173
170
|
|
|
174
171
|
// Check $and, $or, $nor arrays
|
|
175
172
|
for (const key of ['$and', '$or', '$nor']) {
|
|
@@ -186,7 +183,7 @@ function isEmptyFilter(obj) {
|
|
|
186
183
|
|
|
187
184
|
// Helper function to check for empty/invalid filter
|
|
188
185
|
function checkRequireFilter(filter, options) {
|
|
189
|
-
if (options
|
|
186
|
+
if (options?.requireFilter && isEmptyFilter(filter)) {
|
|
190
187
|
throw new Error('Empty or invalid filter not allowed with requireFilter enabled');
|
|
191
188
|
}
|
|
192
189
|
}
|
|
@@ -457,8 +454,8 @@ Query.prototype.clone = function() {
|
|
|
457
454
|
* @api public
|
|
458
455
|
*/
|
|
459
456
|
|
|
460
|
-
Query.prototype.slice = function() {
|
|
461
|
-
if (
|
|
457
|
+
Query.prototype.slice = function(...args) {
|
|
458
|
+
if (args.length === 0) {
|
|
462
459
|
return this;
|
|
463
460
|
}
|
|
464
461
|
|
|
@@ -467,8 +464,8 @@ Query.prototype.slice = function() {
|
|
|
467
464
|
let path;
|
|
468
465
|
let val;
|
|
469
466
|
|
|
470
|
-
if (
|
|
471
|
-
const arg =
|
|
467
|
+
if (args.length === 1) {
|
|
468
|
+
const arg = args[0];
|
|
472
469
|
if (typeof arg === 'object' && !Array.isArray(arg)) {
|
|
473
470
|
const keys = Object.keys(arg);
|
|
474
471
|
const numKeys = keys.length;
|
|
@@ -479,19 +476,19 @@ Query.prototype.slice = function() {
|
|
|
479
476
|
}
|
|
480
477
|
this._ensurePath('slice');
|
|
481
478
|
path = this._path;
|
|
482
|
-
val =
|
|
483
|
-
} else if (
|
|
484
|
-
if ('number' === typeof
|
|
479
|
+
val = args[0];
|
|
480
|
+
} else if (args.length === 2) {
|
|
481
|
+
if ('number' === typeof args[0]) {
|
|
485
482
|
this._ensurePath('slice');
|
|
486
483
|
path = this._path;
|
|
487
|
-
val = [
|
|
484
|
+
val = [args[0], args[1]];
|
|
488
485
|
} else {
|
|
489
|
-
path =
|
|
490
|
-
val =
|
|
486
|
+
path = args[0];
|
|
487
|
+
val = args[1];
|
|
491
488
|
}
|
|
492
|
-
} else if (
|
|
493
|
-
path =
|
|
494
|
-
val = [
|
|
489
|
+
} else if (args.length === 3) {
|
|
490
|
+
path = args[0];
|
|
491
|
+
val = [args[1], args[2]];
|
|
495
492
|
}
|
|
496
493
|
|
|
497
494
|
const p = {};
|
|
@@ -2006,7 +2003,7 @@ Query.prototype._fieldsForExec = function() {
|
|
|
2006
2003
|
if (this._fields == null) {
|
|
2007
2004
|
return null;
|
|
2008
2005
|
}
|
|
2009
|
-
if (
|
|
2006
|
+
if (utils.hasOwnKeys(this._fields) === false) {
|
|
2010
2007
|
return null;
|
|
2011
2008
|
}
|
|
2012
2009
|
return clone(this._fields);
|
|
@@ -2104,10 +2101,7 @@ Query.prototype._optionsForExec = function(model) {
|
|
|
2104
2101
|
options.session = asyncLocalStorage.session;
|
|
2105
2102
|
}
|
|
2106
2103
|
|
|
2107
|
-
const readPreference = model
|
|
2108
|
-
model.schema &&
|
|
2109
|
-
model.schema.options &&
|
|
2110
|
-
model.schema.options.read;
|
|
2104
|
+
const readPreference = model?.schema?.options?.read;
|
|
2111
2105
|
if (!('readPreference' in options) && readPreference) {
|
|
2112
2106
|
options.readPreference = readPreference;
|
|
2113
2107
|
}
|
|
@@ -2413,13 +2407,15 @@ Query.prototype._find = async function _find() {
|
|
|
2413
2407
|
const mongooseOptions = this._mongooseOptions;
|
|
2414
2408
|
const userProvidedFields = this._userProvidedFields || {};
|
|
2415
2409
|
|
|
2416
|
-
|
|
2417
|
-
|
|
2410
|
+
const dbOptions = this.model.db.options;
|
|
2411
|
+
const baseOptions = this.model.base.options;
|
|
2412
|
+
applyGlobalMaxTimeMS(this.options, dbOptions, baseOptions);
|
|
2413
|
+
applyGlobalDiskUse(this.options, dbOptions, baseOptions);
|
|
2418
2414
|
|
|
2419
2415
|
// Separate options to pass down to `completeMany()` in case we need to
|
|
2420
2416
|
// set a session on the document
|
|
2421
2417
|
const completeManyOptions = {
|
|
2422
|
-
session: this
|
|
2418
|
+
session: this?.options?.session || null,
|
|
2423
2419
|
lean: mongooseOptions.lean || null
|
|
2424
2420
|
};
|
|
2425
2421
|
|
|
@@ -2440,7 +2436,7 @@ Query.prototype._find = async function _find() {
|
|
|
2440
2436
|
|
|
2441
2437
|
if (!mongooseOptions.populate) {
|
|
2442
2438
|
const versionKey = this.schema.options.versionKey;
|
|
2443
|
-
if (mongooseOptions.lean
|
|
2439
|
+
if (mongooseOptions.lean?.versionKey === false && versionKey) {
|
|
2444
2440
|
docs.forEach((doc) => {
|
|
2445
2441
|
if (versionKey in doc) {
|
|
2446
2442
|
delete doc[versionKey];
|
|
@@ -2561,7 +2557,7 @@ Query.prototype.merge = function(source) {
|
|
|
2561
2557
|
utils.merge(this._conditions, { _id: source }, opts);
|
|
2562
2558
|
|
|
2563
2559
|
return this;
|
|
2564
|
-
} else if (source
|
|
2560
|
+
} else if (source?.$__) {
|
|
2565
2561
|
source = source.toObject(internalToObjectOptions);
|
|
2566
2562
|
}
|
|
2567
2563
|
|
|
@@ -2635,7 +2631,7 @@ Query.prototype._completeOne = function(doc, res, projection, callback) {
|
|
|
2635
2631
|
|
|
2636
2632
|
if (!mongooseOptions.populate) {
|
|
2637
2633
|
const versionKey = this.schema.options.versionKey;
|
|
2638
|
-
if (mongooseOptions.lean
|
|
2634
|
+
if (mongooseOptions.lean?.versionKey === false && versionKey) {
|
|
2639
2635
|
if (versionKey in doc) {
|
|
2640
2636
|
delete doc[versionKey];
|
|
2641
2637
|
}
|
|
@@ -2712,8 +2708,10 @@ Query.prototype._findOne = async function _findOne() {
|
|
|
2712
2708
|
throw err;
|
|
2713
2709
|
}
|
|
2714
2710
|
|
|
2715
|
-
|
|
2716
|
-
|
|
2711
|
+
const dbOptions = this.model.db.options;
|
|
2712
|
+
const baseOptions = this.model.base.options;
|
|
2713
|
+
applyGlobalMaxTimeMS(this.options, dbOptions, baseOptions);
|
|
2714
|
+
applyGlobalDiskUse(this.options, dbOptions, baseOptions);
|
|
2717
2715
|
|
|
2718
2716
|
const options = this._optionsForExec();
|
|
2719
2717
|
|
|
@@ -2808,8 +2806,10 @@ Query.prototype._countDocuments = async function _countDocuments() {
|
|
|
2808
2806
|
throw this.error();
|
|
2809
2807
|
}
|
|
2810
2808
|
|
|
2811
|
-
|
|
2812
|
-
|
|
2809
|
+
const dbOptions = this.model.db.options;
|
|
2810
|
+
const baseOptions = this.model.base.options;
|
|
2811
|
+
applyGlobalMaxTimeMS(this.options, dbOptions, baseOptions);
|
|
2812
|
+
applyGlobalDiskUse(this.options, dbOptions, baseOptions);
|
|
2813
2813
|
|
|
2814
2814
|
const options = this._optionsForExec();
|
|
2815
2815
|
|
|
@@ -2836,7 +2836,7 @@ Query.prototype._applyTranslateAliases = function _applyTranslateAliases() {
|
|
|
2836
2836
|
return;
|
|
2837
2837
|
}
|
|
2838
2838
|
|
|
2839
|
-
if (this.model?.schema?.aliases &&
|
|
2839
|
+
if (this.model?.schema?.aliases && utils.hasOwnKeys(this.model.schema.aliases)) {
|
|
2840
2840
|
this.model.translateAliases(this._conditions, true);
|
|
2841
2841
|
this.model.translateAliases(this._fields, true);
|
|
2842
2842
|
this.model.translateAliases(this._update, true);
|
|
@@ -2974,8 +2974,10 @@ Query.prototype.__distinct = async function __distinct() {
|
|
|
2974
2974
|
throw this.error();
|
|
2975
2975
|
}
|
|
2976
2976
|
|
|
2977
|
-
|
|
2978
|
-
|
|
2977
|
+
const dbOptions = this.model.db.options;
|
|
2978
|
+
const baseOptions = this.model.base.options;
|
|
2979
|
+
applyGlobalMaxTimeMS(this.options, dbOptions, baseOptions);
|
|
2980
|
+
applyGlobalDiskUse(this.options, dbOptions, baseOptions);
|
|
2979
2981
|
|
|
2980
2982
|
const options = this._optionsForExec();
|
|
2981
2983
|
|
|
@@ -3075,7 +3077,7 @@ Query.prototype.sort = function(arg, options) {
|
|
|
3075
3077
|
if (this.options.sort == null) {
|
|
3076
3078
|
this.options.sort = {};
|
|
3077
3079
|
}
|
|
3078
|
-
if (options
|
|
3080
|
+
if (options?.override) {
|
|
3079
3081
|
this.options.sort = {};
|
|
3080
3082
|
}
|
|
3081
3083
|
const sort = this.options.sort;
|
|
@@ -3345,13 +3347,13 @@ function completeOne(model, doc, res, options, fields, userProvidedFields, pop,
|
|
|
3345
3347
|
*/
|
|
3346
3348
|
|
|
3347
3349
|
function prepareDiscriminatorCriteria(query) {
|
|
3348
|
-
if (!query
|
|
3350
|
+
if (!query?.model?.schema) {
|
|
3349
3351
|
return;
|
|
3350
3352
|
}
|
|
3351
3353
|
|
|
3352
3354
|
const schema = query.model.schema;
|
|
3353
3355
|
|
|
3354
|
-
if (schema
|
|
3356
|
+
if (schema?.discriminatorMapping && !schema.discriminatorMapping.isRoot) {
|
|
3355
3357
|
query._conditions[schema.discriminatorMapping.key] = schema.discriminatorMapping.value;
|
|
3356
3358
|
}
|
|
3357
3359
|
}
|
|
@@ -3492,8 +3494,10 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
|
|
|
3492
3494
|
throw this.error();
|
|
3493
3495
|
}
|
|
3494
3496
|
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
+
const dbOptions = this.model.db.options;
|
|
3498
|
+
const baseOptions = this.model.base.options;
|
|
3499
|
+
applyGlobalMaxTimeMS(this.options, dbOptions, baseOptions);
|
|
3500
|
+
applyGlobalDiskUse(this.options, dbOptions, baseOptions);
|
|
3497
3501
|
|
|
3498
3502
|
if ('strict' in this.options) {
|
|
3499
3503
|
this._mongooseOptions.strict = this.options.strict;
|
|
@@ -3509,7 +3513,7 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
|
|
|
3509
3513
|
this._update = setDefaultsOnInsert(this._conditions, this.model.schema,
|
|
3510
3514
|
this._update, _opts);
|
|
3511
3515
|
|
|
3512
|
-
if (!this._update ||
|
|
3516
|
+
if (!this._update || utils.hasOwnKeys(this._update) === false) {
|
|
3513
3517
|
if (options.upsert) {
|
|
3514
3518
|
// still need to do the upsert to empty doc
|
|
3515
3519
|
const $set = clone(this._update);
|
|
@@ -3526,7 +3530,7 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
|
|
|
3526
3530
|
// In order to make MongoDB 2.6 happy (see
|
|
3527
3531
|
// https://jira.mongodb.org/browse/SERVER-12266 and related issues)
|
|
3528
3532
|
// if we have an actual update document but $set is empty, junk the $set.
|
|
3529
|
-
if (this._update.$set &&
|
|
3533
|
+
if (this._update.$set && utils.hasOwnKeys(this._update.$set) === false) {
|
|
3530
3534
|
delete this._update.$set;
|
|
3531
3535
|
}
|
|
3532
3536
|
}
|
|
@@ -4015,7 +4019,7 @@ Query.prototype._mergeUpdate = function(update) {
|
|
|
4015
4019
|
this._update = Array.isArray(update) ? [] : {};
|
|
4016
4020
|
}
|
|
4017
4021
|
|
|
4018
|
-
if (update == null || (typeof update === 'object' &&
|
|
4022
|
+
if (update == null || (typeof update === 'object' && utils.hasOwnKeys(update) === false)) {
|
|
4019
4023
|
return;
|
|
4020
4024
|
}
|
|
4021
4025
|
|
|
@@ -4067,7 +4071,7 @@ async function _updateThunk(op) {
|
|
|
4067
4071
|
} else {
|
|
4068
4072
|
this._update = this._castUpdate(this._update);
|
|
4069
4073
|
|
|
4070
|
-
if (this._update == null ||
|
|
4074
|
+
if (this._update == null || utils.hasOwnKeys(this._update) === false) {
|
|
4071
4075
|
return { acknowledged: false };
|
|
4072
4076
|
}
|
|
4073
4077
|
|
|
@@ -4406,7 +4410,7 @@ function _update(query, op, filter, doc, options, callback) {
|
|
|
4406
4410
|
}
|
|
4407
4411
|
|
|
4408
4412
|
const updatePipeline = query?.model?.base?.options?.updatePipeline;
|
|
4409
|
-
if (updatePipeline != null &&
|
|
4413
|
+
if (updatePipeline != null && options?.updatePipeline == null) {
|
|
4410
4414
|
options = options || {};
|
|
4411
4415
|
options.updatePipeline = updatePipeline;
|
|
4412
4416
|
}
|
|
@@ -4501,7 +4505,7 @@ Query.prototype.orFail = function(err) {
|
|
|
4501
4505
|
case 'replaceOne':
|
|
4502
4506
|
case 'updateMany':
|
|
4503
4507
|
case 'updateOne':
|
|
4504
|
-
if (res
|
|
4508
|
+
if (res?.matchedCount === 0) {
|
|
4505
4509
|
throw _orFailError(err, this);
|
|
4506
4510
|
}
|
|
4507
4511
|
break;
|
|
@@ -4595,7 +4599,7 @@ Query.prototype.exec = async function exec(op) {
|
|
|
4595
4599
|
throw new MongooseError('Query has invalid `op`: "' + this.op + '"');
|
|
4596
4600
|
}
|
|
4597
4601
|
|
|
4598
|
-
if (this.options
|
|
4602
|
+
if (this.options?.sort && typeof this.options.sort === 'object' && Object.hasOwn(this.options.sort, '')) {
|
|
4599
4603
|
throw new Error('Invalid field "" passed to sort()');
|
|
4600
4604
|
}
|
|
4601
4605
|
|
|
@@ -4810,7 +4814,7 @@ Query.prototype._castUpdate = function _castUpdate(obj) {
|
|
|
4810
4814
|
let schema = this.schema;
|
|
4811
4815
|
|
|
4812
4816
|
const discriminatorKey = schema.options.discriminatorKey;
|
|
4813
|
-
const baseSchema = schema._baseSchema
|
|
4817
|
+
const baseSchema = schema._baseSchema || schema;
|
|
4814
4818
|
if (this._mongooseOptions.overwriteDiscriminatorKey &&
|
|
4815
4819
|
obj[discriminatorKey] != null &&
|
|
4816
4820
|
baseSchema.discriminators) {
|
|
@@ -4888,8 +4892,7 @@ Query.prototype._castUpdate = function _castUpdate(obj) {
|
|
|
4888
4892
|
* @api public
|
|
4889
4893
|
*/
|
|
4890
4894
|
|
|
4891
|
-
Query.prototype.populate = function() {
|
|
4892
|
-
const args = Array.from(arguments);
|
|
4895
|
+
Query.prototype.populate = function(...args) {
|
|
4893
4896
|
// Bail when given no truthy arguments
|
|
4894
4897
|
if (!args.some(Boolean)) {
|
|
4895
4898
|
return this;
|
|
@@ -4902,7 +4905,7 @@ Query.prototype.populate = function() {
|
|
|
4902
4905
|
if (opts.lean != null) {
|
|
4903
4906
|
const lean = opts.lean;
|
|
4904
4907
|
for (const populateOptions of res) {
|
|
4905
|
-
if (
|
|
4908
|
+
if (populateOptions?.options?.lean == null) {
|
|
4906
4909
|
populateOptions.options = populateOptions.options || {};
|
|
4907
4910
|
populateOptions.options.lean = lean;
|
|
4908
4911
|
}
|
|
@@ -4917,7 +4920,7 @@ Query.prototype.populate = function() {
|
|
|
4917
4920
|
|
|
4918
4921
|
for (const populateOptions of res) {
|
|
4919
4922
|
const path = populateOptions.path;
|
|
4920
|
-
if (pop[path]
|
|
4923
|
+
if (pop[path]?.populate && populateOptions.populate) {
|
|
4921
4924
|
populateOptions.populate = pop[path].populate.concat(populateOptions.populate);
|
|
4922
4925
|
}
|
|
4923
4926
|
|
|
@@ -4999,7 +5002,7 @@ Query.prototype.cast = function(model, obj) {
|
|
|
4999
5002
|
model = getDiscriminatorByValue(model.discriminators, obj[discriminatorKey]) || model;
|
|
5000
5003
|
}
|
|
5001
5004
|
|
|
5002
|
-
const opts = { upsert: this.options
|
|
5005
|
+
const opts = { upsert: this.options?.upsert };
|
|
5003
5006
|
if (this.options) {
|
|
5004
5007
|
if ('strict' in this.options) {
|
|
5005
5008
|
opts.strict = this.options.strict;
|
|
@@ -5197,7 +5200,7 @@ Query.prototype.cursor = function cursor(opts) {
|
|
|
5197
5200
|
Query.prototype.tailable = function(val, opts) {
|
|
5198
5201
|
// we need to support the tailable({ awaitData : true }) as well as the
|
|
5199
5202
|
// tailable(true, {awaitData :true}) syntax that mquery does not support
|
|
5200
|
-
if (
|
|
5203
|
+
if (typeof val?.constructor === 'function' && val.constructor.name === 'Object') {
|
|
5201
5204
|
opts = val;
|
|
5202
5205
|
val = true;
|
|
5203
5206
|
}
|
|
@@ -5559,11 +5562,11 @@ Query.prototype.center = Query.base.circle;
|
|
|
5559
5562
|
*/
|
|
5560
5563
|
|
|
5561
5564
|
Query.prototype.centerSphere = function() {
|
|
5562
|
-
if (
|
|
5565
|
+
if (typeof arguments[0]?.constructor === 'function' && arguments[0].constructor.name === 'Object') {
|
|
5563
5566
|
arguments[0].spherical = true;
|
|
5564
5567
|
}
|
|
5565
5568
|
|
|
5566
|
-
if (
|
|
5569
|
+
if (typeof arguments[1]?.constructor === 'function' && arguments[1].constructor.name === 'Object') {
|
|
5567
5570
|
arguments[1].spherical = true;
|
|
5568
5571
|
}
|
|
5569
5572
|
|
package/lib/queryHelpers.js
CHANGED
|
@@ -30,11 +30,11 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
|
|
30
30
|
// lean options should trickle through all queries
|
|
31
31
|
if (options.lean != null) {
|
|
32
32
|
pop
|
|
33
|
-
.filter(p =>
|
|
33
|
+
.filter(p => p?.options?.lean == null)
|
|
34
34
|
.forEach(makeLean(options.lean));
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const session = query
|
|
37
|
+
const session = query?.options?.session || null;
|
|
38
38
|
if (session != null) {
|
|
39
39
|
pop.forEach(path => {
|
|
40
40
|
if (path.options == null) {
|
|
@@ -80,7 +80,7 @@ exports.createModel = function createModel(model, doc, fields, userProvidedField
|
|
|
80
80
|
model.schema.discriminatorMapping :
|
|
81
81
|
null;
|
|
82
82
|
|
|
83
|
-
const key = discriminatorMapping
|
|
83
|
+
const key = discriminatorMapping?.isRoot ?
|
|
84
84
|
discriminatorMapping.key :
|
|
85
85
|
null;
|
|
86
86
|
|
|
@@ -179,10 +179,10 @@ exports.applyPaths = function applyPaths(fields, schema, sanitizeProjection) {
|
|
|
179
179
|
// inclusive, minus path is treated as equivalent to `key: 0`.
|
|
180
180
|
// But we also allow using `-name` to remove `name` from an inclusive
|
|
181
181
|
// projection if `name` has schema-level `select: true`.
|
|
182
|
-
if (
|
|
182
|
+
if (!type?.selected || exclude !== false) {
|
|
183
183
|
fields[path] = 0;
|
|
184
184
|
exclude = true;
|
|
185
|
-
} else if (type
|
|
185
|
+
} else if (type?.selected && exclude === false) {
|
|
186
186
|
// Make a note of minus paths that are overwriting paths that are
|
|
187
187
|
// included by default.
|
|
188
188
|
minusPathsToSkip.add(path);
|
|
@@ -204,10 +204,7 @@ exports.applyPaths = function applyPaths(fields, schema, sanitizeProjection) {
|
|
|
204
204
|
}
|
|
205
205
|
break;
|
|
206
206
|
case false:
|
|
207
|
-
if (schema
|
|
208
|
-
schema.paths['_id'] &&
|
|
209
|
-
schema.paths['_id'].options &&
|
|
210
|
-
schema.paths['_id'].options.select === false) {
|
|
207
|
+
if (schema?.paths['_id']?.options?.select === false) {
|
|
211
208
|
fields._id = 0;
|
|
212
209
|
}
|
|
213
210
|
|
|
@@ -260,7 +257,7 @@ exports.applyPaths = function applyPaths(fields, schema, sanitizeProjection) {
|
|
|
260
257
|
if (type.$isSchemaMap || path.endsWith('.$*')) {
|
|
261
258
|
const plusPath = '+' + path;
|
|
262
259
|
const hasPlusPath = fields && plusPath in fields;
|
|
263
|
-
if (type.options
|
|
260
|
+
if (type.options?.select === false && !hasPlusPath) {
|
|
264
261
|
excluded.push(path);
|
|
265
262
|
}
|
|
266
263
|
return;
|
|
@@ -352,7 +349,7 @@ exports.applyPaths = function applyPaths(fields, schema, sanitizeProjection) {
|
|
|
352
349
|
// Special case: if user has included a parent path of a discriminator key,
|
|
353
350
|
// don't explicitly project in the discriminator key because that will
|
|
354
351
|
// project out everything else under the parent path
|
|
355
|
-
if (!exclude && (type
|
|
352
|
+
if (!exclude && (type?.options?.$skipDiscriminatorCheck || false)) {
|
|
356
353
|
let cur = '';
|
|
357
354
|
for (let i = 0; i < pieces.length; ++i) {
|
|
358
355
|
cur += (cur.length === 0 ? '' : '.') + pieces[i];
|
|
@@ -378,7 +375,7 @@ function makeLean(val) {
|
|
|
378
375
|
return function(option) {
|
|
379
376
|
option.options || (option.options = {});
|
|
380
377
|
|
|
381
|
-
if (
|
|
378
|
+
if (Array.isArray(val?.virtuals)) {
|
|
382
379
|
val = Object.assign({}, val);
|
|
383
380
|
val.virtuals = val.virtuals.
|
|
384
381
|
filter(path => typeof path === 'string' && path.startsWith(option.path + '.')).
|
package/lib/schema/array.js
CHANGED
|
@@ -47,7 +47,7 @@ function SchemaArray(key, cast, options, schemaOptions, parentSchema) {
|
|
|
47
47
|
EmbeddedDoc || (EmbeddedDoc = require('../types').Embedded);
|
|
48
48
|
|
|
49
49
|
let typeKey = 'type';
|
|
50
|
-
if (schemaOptions
|
|
50
|
+
if (schemaOptions?.typeKey) {
|
|
51
51
|
typeKey = schemaOptions.typeKey;
|
|
52
52
|
}
|
|
53
53
|
this.schemaOptions = schemaOptions;
|
|
@@ -66,7 +66,7 @@ function SchemaArray(key, cast, options, schemaOptions, parentSchema) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
if (options
|
|
69
|
+
if (options?.ref != null && castOptions.ref == null) {
|
|
70
70
|
castOptions.ref = options.ref;
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -255,9 +255,7 @@ SchemaArray.prototype.checkRequired = function checkRequired(value, doc) {
|
|
|
255
255
|
SchemaArray.prototype.enum = function() {
|
|
256
256
|
let arr = this;
|
|
257
257
|
while (true) {
|
|
258
|
-
const instance = arr
|
|
259
|
-
arr.embeddedSchemaType &&
|
|
260
|
-
arr.embeddedSchemaType.instance;
|
|
258
|
+
const instance = arr?.embeddedSchemaType?.instance;
|
|
261
259
|
if (instance === 'Array') {
|
|
262
260
|
arr = arr.embeddedSchemaType;
|
|
263
261
|
continue;
|
|
@@ -287,7 +285,7 @@ SchemaArray.prototype.enum = function() {
|
|
|
287
285
|
*/
|
|
288
286
|
|
|
289
287
|
SchemaArray.prototype.applyGetters = function(value, scope) {
|
|
290
|
-
if (scope
|
|
288
|
+
if (scope?.$__ != null && scope.$populated(this.path)) {
|
|
291
289
|
// means the object id was populated
|
|
292
290
|
return value;
|
|
293
291
|
}
|
|
@@ -376,7 +374,7 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
376
374
|
value = MongooseArray(rawValue, path, doc, this);
|
|
377
375
|
rawValue = value.__array;
|
|
378
376
|
|
|
379
|
-
if (init && doc
|
|
377
|
+
if (init && doc?.$__ != null && doc.$populated(this.path)) {
|
|
380
378
|
return value;
|
|
381
379
|
}
|
|
382
380
|
|
|
@@ -411,11 +409,11 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
411
409
|
return value;
|
|
412
410
|
}
|
|
413
411
|
|
|
414
|
-
const castNonArraysOption = this.options.castNonArrays
|
|
412
|
+
const castNonArraysOption = this.options.castNonArrays ?? SchemaArray.options.castNonArrays;
|
|
415
413
|
if (init || castNonArraysOption) {
|
|
416
414
|
// gh-2442: if we're loading this from the db and its not an array, mark
|
|
417
415
|
// the whole array as modified.
|
|
418
|
-
if (
|
|
416
|
+
if (doc && init) {
|
|
419
417
|
doc.markModified(this.path);
|
|
420
418
|
}
|
|
421
419
|
return this.cast([value], doc, init);
|
|
@@ -586,12 +584,12 @@ function cast$all(val, context) {
|
|
|
586
584
|
return v;
|
|
587
585
|
}
|
|
588
586
|
if (v.$elemMatch != null) {
|
|
589
|
-
return { $elemMatch: cast(this.embeddedSchemaType.schema, v.$elemMatch, null, this
|
|
587
|
+
return { $elemMatch: cast(this.embeddedSchemaType.schema, v.$elemMatch, null, this?.$$context) };
|
|
590
588
|
}
|
|
591
589
|
|
|
592
590
|
const o = {};
|
|
593
591
|
o[this.path] = v;
|
|
594
|
-
return cast(this.embeddedSchemaType.schema, o, null, this
|
|
592
|
+
return cast(this.embeddedSchemaType.schema, o, null, this?.$$context)[this.path];
|
|
595
593
|
}, this);
|
|
596
594
|
|
|
597
595
|
return this.castForQuery(null, val, context);
|
|
@@ -639,7 +637,7 @@ function createLogicalQueryOperatorHandler(op) {
|
|
|
639
637
|
|
|
640
638
|
const ret = [];
|
|
641
639
|
for (const obj of val) {
|
|
642
|
-
ret.push(cast(this.embeddedSchemaType.schema ?? context.schema, obj, null, this
|
|
640
|
+
ret.push(cast(this.embeddedSchemaType.schema ?? context.schema, obj, null, this?.$$context));
|
|
643
641
|
}
|
|
644
642
|
|
|
645
643
|
return ret;
|
package/lib/schema/buffer.js
CHANGED
|
@@ -50,7 +50,7 @@ SchemaBuffer.prototype.OptionsConstructor = SchemaBufferOptions;
|
|
|
50
50
|
* ignore
|
|
51
51
|
*/
|
|
52
52
|
|
|
53
|
-
SchemaBuffer._checkRequired = v => !!
|
|
53
|
+
SchemaBuffer._checkRequired = v => !!v?.length;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Sets a default option for all Buffer instances.
|
|
@@ -146,12 +146,12 @@ SchemaBuffer.prototype.checkRequired = function(value, doc) {
|
|
|
146
146
|
SchemaBuffer.prototype.cast = function(value, doc, init, prev, options) {
|
|
147
147
|
let ret;
|
|
148
148
|
if (SchemaType._isRef(this, value, doc, init)) {
|
|
149
|
-
if (value
|
|
149
|
+
if (value?.isMongooseBuffer) {
|
|
150
150
|
return value;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
if (Buffer.isBuffer(value)) {
|
|
154
|
-
if (!value
|
|
154
|
+
if (!value?.isMongooseBuffer) {
|
|
155
155
|
value = new MongooseBuffer(value, [this.path, doc]);
|
|
156
156
|
if (this.options.subtype != null) {
|
|
157
157
|
value._subtype = this.options.subtype;
|
|
@@ -175,16 +175,16 @@ SchemaBuffer.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
// documents
|
|
178
|
-
if (value
|
|
178
|
+
if (value?._id) {
|
|
179
179
|
value = value._id;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
if (value
|
|
182
|
+
if (value?.isMongooseBuffer) {
|
|
183
183
|
return value;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
if (Buffer.isBuffer(value)) {
|
|
187
|
-
if (!value
|
|
187
|
+
if (!value?.isMongooseBuffer) {
|
|
188
188
|
value = new MongooseBuffer(value, [this.path, doc]);
|
|
189
189
|
if (this.options.subtype != null) {
|
|
190
190
|
value._subtype = this.options.subtype;
|
|
@@ -41,19 +41,18 @@ let Subdocument;
|
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
43
|
function SchemaDocumentArray(key, schema, options, schemaOptions, parentSchema) {
|
|
44
|
-
if (schema.options
|
|
44
|
+
if (schema.options?.timeseries) {
|
|
45
45
|
throw new InvalidSchemaOptionError(key, 'timeseries');
|
|
46
46
|
}
|
|
47
|
-
const schemaTypeIdOption = SchemaDocumentArray.defaultOptions
|
|
48
|
-
SchemaDocumentArray.defaultOptions._id;
|
|
47
|
+
const schemaTypeIdOption = SchemaDocumentArray.defaultOptions?._id;
|
|
49
48
|
if (schemaTypeIdOption != null) {
|
|
50
49
|
schemaOptions = schemaOptions || {};
|
|
51
50
|
schemaOptions._id = schemaTypeIdOption;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
if (schemaOptions
|
|
53
|
+
if (schemaOptions?._id != null) {
|
|
55
54
|
schema = handleIdOption(schema, schemaOptions);
|
|
56
|
-
} else if (options
|
|
55
|
+
} else if (options?._id != null) {
|
|
57
56
|
schema = handleIdOption(schema, options);
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -150,7 +149,7 @@ function _createConstructor(schema, options, baseClass) {
|
|
|
150
149
|
|
|
151
150
|
schema._preCompile();
|
|
152
151
|
|
|
153
|
-
const proto = baseClass
|
|
152
|
+
const proto = baseClass?.prototype ?? Subdocument.prototype;
|
|
154
153
|
EmbeddedDocument.prototype = Object.create(proto);
|
|
155
154
|
EmbeddedDocument.prototype.$__setSchema(schema);
|
|
156
155
|
EmbeddedDocument.schema = schema;
|
|
@@ -260,7 +259,7 @@ SchemaDocumentArray.prototype.doValidate = async function doValidate(array, scop
|
|
|
260
259
|
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
|
261
260
|
}
|
|
262
261
|
|
|
263
|
-
if (options
|
|
262
|
+
if (options?.validateModifiedOnly && !doc.$isModified()) {
|
|
264
263
|
continue;
|
|
265
264
|
}
|
|
266
265
|
|
|
@@ -287,7 +286,7 @@ SchemaDocumentArray.prototype.doValidateSync = function(array, scope, options) {
|
|
|
287
286
|
return schemaTypeError;
|
|
288
287
|
}
|
|
289
288
|
|
|
290
|
-
const count = array
|
|
289
|
+
const count = array?.length;
|
|
291
290
|
let resultError = null;
|
|
292
291
|
|
|
293
292
|
if (!count) {
|
|
@@ -312,7 +311,7 @@ SchemaDocumentArray.prototype.doValidateSync = function(array, scope, options) {
|
|
|
312
311
|
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
|
313
312
|
}
|
|
314
313
|
|
|
315
|
-
if (options
|
|
314
|
+
if (options?.validateModifiedOnly && !doc.$isModified()) {
|
|
316
315
|
continue;
|
|
317
316
|
}
|
|
318
317
|
|
|
@@ -339,7 +338,7 @@ SchemaDocumentArray.prototype.getDefault = function(scope, init, options) {
|
|
|
339
338
|
return ret;
|
|
340
339
|
}
|
|
341
340
|
|
|
342
|
-
if (options
|
|
341
|
+
if (options?.skipCast) {
|
|
343
342
|
return ret;
|
|
344
343
|
}
|
|
345
344
|
|
|
@@ -386,7 +385,7 @@ SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
386
385
|
MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentArray'));
|
|
387
386
|
|
|
388
387
|
// Skip casting if `value` is the same as the previous value, no need to cast. See gh-9266
|
|
389
|
-
if (value
|
|
388
|
+
if (value?.[arrayPathSymbol] != null && value === prev) {
|
|
390
389
|
return value;
|
|
391
390
|
}
|
|
392
391
|
|
|
@@ -463,7 +462,7 @@ SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {
|
|
|
463
462
|
subdoc = new Constructor(null, value, initDocumentOptions, selected, i);
|
|
464
463
|
rawArray[i] = subdoc.$init(rawArray[i], options);
|
|
465
464
|
} else {
|
|
466
|
-
if (
|
|
465
|
+
if (typeof prev?.id === 'function') {
|
|
467
466
|
subdoc = prev.id(rawArray[i]._id);
|
|
468
467
|
}
|
|
469
468
|
|
|
@@ -621,23 +620,16 @@ function cast$elemMatch(val, context) {
|
|
|
621
620
|
|
|
622
621
|
// Is this an embedded discriminator and is the discriminator key set?
|
|
623
622
|
// If so, use the discriminator schema. See gh-7449
|
|
624
|
-
const discriminatorKey = this
|
|
625
|
-
|
|
626
|
-
this.Constructor.schema &&
|
|
627
|
-
this.Constructor.schema.options &&
|
|
628
|
-
this.Constructor.schema.options.discriminatorKey;
|
|
629
|
-
const discriminators = this &&
|
|
630
|
-
this.Constructor &&
|
|
631
|
-
this.Constructor.schema &&
|
|
632
|
-
this.Constructor.schema.discriminators || {};
|
|
623
|
+
const discriminatorKey = this?.Constructor?.schema?.options?.discriminatorKey;
|
|
624
|
+
const discriminators = this?.Constructor?.schema?.discriminators || {};
|
|
633
625
|
if (discriminatorKey != null &&
|
|
634
626
|
val[discriminatorKey] != null &&
|
|
635
627
|
discriminators[val[discriminatorKey]] != null) {
|
|
636
|
-
return cast(discriminators[val[discriminatorKey]], val, null, this
|
|
628
|
+
return cast(discriminators[val[discriminatorKey]], val, null, this?.$$context);
|
|
637
629
|
}
|
|
638
630
|
|
|
639
631
|
const schema = this.Constructor.schema ?? context.schema;
|
|
640
|
-
return cast(schema, val, null, this
|
|
632
|
+
return cast(schema, val, null, this?.$$context);
|
|
641
633
|
}
|
|
642
634
|
|
|
643
635
|
/**
|