mongoose 8.8.4 → 8.9.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/dist/browser.umd.js +1 -1
- package/lib/cast/double.js +50 -0
- package/lib/cast/int32.js +36 -0
- package/lib/connection.js +220 -18
- package/lib/cursor/aggregationCursor.js +1 -2
- package/lib/document.js +19 -7
- package/lib/drivers/node-mongodb-native/collection.js +0 -1
- package/lib/drivers/node-mongodb-native/connection.js +0 -4
- package/lib/helpers/clone.js +5 -0
- package/lib/helpers/model/castBulkWrite.js +218 -205
- package/lib/helpers/model/discriminator.js +1 -0
- package/lib/helpers/populate/getModelsMapForPopulate.js +7 -0
- package/lib/helpers/schema/getIndexes.js +5 -0
- package/lib/model.js +71 -107
- package/lib/mongoose.js +20 -20
- package/lib/query.js +6 -20
- package/lib/queryHelpers.js +13 -32
- package/lib/schema/bigint.js +2 -2
- package/lib/schema/double.js +212 -0
- package/lib/schema/index.js +2 -0
- package/lib/schema/int32.js +249 -0
- package/lib/schema/string.js +10 -10
- package/lib/schema.js +60 -7
- package/lib/schemaType.js +36 -8
- package/lib/validOptions.js +1 -0
- package/package.json +5 -5
- package/types/expressions.d.ts +102 -0
- package/types/index.d.ts +1 -1
- package/types/indexes.d.ts +4 -2
- package/types/inferschematype.d.ts +29 -27
- package/types/populate.d.ts +2 -0
- package/types/schematypes.d.ts +34 -1
- package/types/types.d.ts +5 -3
package/lib/model.js
CHANGED
|
@@ -436,6 +436,7 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
436
436
|
Model.prototype.$__save = function(options, callback) {
|
|
437
437
|
this.$__handleSave(options, (error, result) => {
|
|
438
438
|
if (error) {
|
|
439
|
+
error = this.$__schema._transformDuplicateKeyError(error);
|
|
439
440
|
const hooks = this.$__schema.s.hooks;
|
|
440
441
|
return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
|
|
441
442
|
callback(error, this);
|
|
@@ -2230,7 +2231,7 @@ Model.$where = function $where() {
|
|
|
2230
2231
|
/**
|
|
2231
2232
|
* Issues a mongodb findOneAndUpdate command.
|
|
2232
2233
|
*
|
|
2233
|
-
* Finds a matching document, updates it according to the `update` arg, passing any `options
|
|
2234
|
+
* Finds a matching document, updates it according to the `update` arg, passing any `options`. A Query object is returned.
|
|
2234
2235
|
*
|
|
2235
2236
|
* #### Example:
|
|
2236
2237
|
*
|
|
@@ -3356,7 +3357,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3356
3357
|
let error;
|
|
3357
3358
|
[res, error] = await this.$__collection.bulkWrite(validOps, options).
|
|
3358
3359
|
then(res => ([res, null])).
|
|
3359
|
-
catch(
|
|
3360
|
+
catch(error => ([null, error]));
|
|
3360
3361
|
|
|
3361
3362
|
if (error) {
|
|
3362
3363
|
if (validationErrors.length > 0) {
|
|
@@ -3642,7 +3643,11 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3642
3643
|
options = options || {};
|
|
3643
3644
|
const ret = {};
|
|
3644
3645
|
|
|
3645
|
-
|
|
3646
|
+
let schema = this.schema;
|
|
3647
|
+
const discriminatorKey = schema.options.discriminatorKey;
|
|
3648
|
+
if (schema.discriminators != null && obj != null && obj[discriminatorKey] != null) {
|
|
3649
|
+
schema = getSchemaDiscriminatorByValue(schema, obj[discriminatorKey]) || schema;
|
|
3650
|
+
}
|
|
3646
3651
|
const paths = Object.keys(schema.paths);
|
|
3647
3652
|
|
|
3648
3653
|
for (const path of paths) {
|
|
@@ -3991,7 +3996,7 @@ function _update(model, op, conditions, doc, options) {
|
|
|
3991
3996
|
/**
|
|
3992
3997
|
* Performs [aggregations](https://www.mongodb.com/docs/manual/aggregation/) on the models collection.
|
|
3993
3998
|
*
|
|
3994
|
-
*
|
|
3999
|
+
* The `aggregate` itself is returned.
|
|
3995
4000
|
*
|
|
3996
4001
|
* This function triggers the following middleware.
|
|
3997
4002
|
*
|
|
@@ -4046,10 +4051,6 @@ Model.aggregate = function aggregate(pipeline, options) {
|
|
|
4046
4051
|
aggregate.option(options);
|
|
4047
4052
|
}
|
|
4048
4053
|
|
|
4049
|
-
if (typeof callback === 'undefined') {
|
|
4050
|
-
return aggregate;
|
|
4051
|
-
}
|
|
4052
|
-
|
|
4053
4054
|
return aggregate;
|
|
4054
4055
|
};
|
|
4055
4056
|
|
|
@@ -4199,6 +4200,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4199
4200
|
* - options: optional query options like sort, limit, etc
|
|
4200
4201
|
* - justOne: optional boolean, if true Mongoose will always set `path` to a document, or `null` if no document was found. If false, Mongoose will always set `path` to an array, which will be empty if no documents are found. Inferred from schema by default.
|
|
4201
4202
|
* - strictPopulate: optional boolean, set to `false` to allow populating paths that aren't in the schema.
|
|
4203
|
+
* - forceRepopulate: optional boolean, defaults to `true`. Set to `false` to prevent Mongoose from repopulating paths that are already populated
|
|
4202
4204
|
*
|
|
4203
4205
|
* #### Example:
|
|
4204
4206
|
*
|
|
@@ -4235,7 +4237,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4235
4237
|
* @param {Boolean} [options.strictPopulate=true] Set to false to allow populating paths that aren't defined in the given model's schema.
|
|
4236
4238
|
* @param {Object} [options.options=null] Additional options like `limit` and `lean`.
|
|
4237
4239
|
* @param {Function} [options.transform=null] Function that Mongoose will call on every populated document that allows you to transform the populated document.
|
|
4238
|
-
* @param {
|
|
4240
|
+
* @param {Boolean} [options.forceRepopulate=true] Set to `false` to prevent Mongoose from repopulating paths that are already populated
|
|
4239
4241
|
* @return {Promise}
|
|
4240
4242
|
* @api public
|
|
4241
4243
|
*/
|
|
@@ -4245,67 +4247,34 @@ Model.populate = async function populate(docs, paths) {
|
|
|
4245
4247
|
if (typeof paths === 'function' || typeof arguments[2] === 'function') {
|
|
4246
4248
|
throw new MongooseError('Model.populate() no longer accepts a callback');
|
|
4247
4249
|
}
|
|
4248
|
-
const _this = this;
|
|
4249
4250
|
// normalized paths
|
|
4250
4251
|
paths = utils.populate(paths);
|
|
4251
|
-
// data that should persist across subPopulate calls
|
|
4252
|
-
const cache = {};
|
|
4253
4252
|
|
|
4254
|
-
return new Promise((resolve, reject) => {
|
|
4255
|
-
_populate(_this, docs, paths, cache, (err, res) => {
|
|
4256
|
-
if (err) {
|
|
4257
|
-
return reject(err);
|
|
4258
|
-
}
|
|
4259
|
-
resolve(res);
|
|
4260
|
-
});
|
|
4261
|
-
});
|
|
4262
|
-
};
|
|
4263
|
-
|
|
4264
|
-
/**
|
|
4265
|
-
* Populate helper
|
|
4266
|
-
*
|
|
4267
|
-
* @param {Model} model the model to use
|
|
4268
|
-
* @param {Document|Array} docs Either a single document or array of documents to populate.
|
|
4269
|
-
* @param {Object} paths
|
|
4270
|
-
* @param {never} cache Unused
|
|
4271
|
-
* @param {Function} [callback] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
|
|
4272
|
-
* @return {Function}
|
|
4273
|
-
* @api private
|
|
4274
|
-
*/
|
|
4275
|
-
|
|
4276
|
-
function _populate(model, docs, paths, cache, callback) {
|
|
4277
|
-
let pending = paths.length;
|
|
4278
4253
|
if (paths.length === 0) {
|
|
4279
|
-
return
|
|
4254
|
+
return docs;
|
|
4280
4255
|
}
|
|
4256
|
+
|
|
4281
4257
|
// each path has its own query options and must be executed separately
|
|
4258
|
+
const promises = [];
|
|
4282
4259
|
for (const path of paths) {
|
|
4283
|
-
|
|
4260
|
+
promises.push(_populatePath(this, docs, path));
|
|
4284
4261
|
}
|
|
4262
|
+
await Promise.all(promises);
|
|
4285
4263
|
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
return callback(err, null);
|
|
4289
|
-
}
|
|
4290
|
-
if (--pending) {
|
|
4291
|
-
return;
|
|
4292
|
-
}
|
|
4293
|
-
callback(null, docs);
|
|
4294
|
-
}
|
|
4295
|
-
}
|
|
4264
|
+
return docs;
|
|
4265
|
+
};
|
|
4296
4266
|
|
|
4297
4267
|
/*!
|
|
4298
|
-
* Populates `docs`
|
|
4268
|
+
* Populates `docs` for a single `populateOptions` instance.
|
|
4299
4269
|
*/
|
|
4300
4270
|
const excludeIdReg = /\s?-_id\s?/;
|
|
4301
4271
|
const excludeIdRegGlobal = /\s?-_id\s?/g;
|
|
4302
4272
|
|
|
4303
|
-
function
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
} else if (options._localModel != null && model.base.options.strictPopulate != null) {
|
|
4273
|
+
async function _populatePath(model, docs, populateOptions) {
|
|
4274
|
+
if (populateOptions.strictPopulate == null) {
|
|
4275
|
+
if (populateOptions._localModel != null && populateOptions._localModel.schema._userProvidedOptions.strictPopulate != null) {
|
|
4276
|
+
populateOptions.strictPopulate = populateOptions._localModel.schema._userProvidedOptions.strictPopulate;
|
|
4277
|
+
} else if (populateOptions._localModel != null && model.base.options.strictPopulate != null) {
|
|
4309
4278
|
populateOptions.strictPopulate = model.base.options.strictPopulate;
|
|
4310
4279
|
} else if (model.base.options.strictPopulate != null) {
|
|
4311
4280
|
populateOptions.strictPopulate = model.base.options.strictPopulate;
|
|
@@ -4317,15 +4286,12 @@ function populate(model, docs, options, callback) {
|
|
|
4317
4286
|
docs = [docs];
|
|
4318
4287
|
}
|
|
4319
4288
|
if (docs.length === 0 || docs.every(utils.isNullOrUndefined)) {
|
|
4320
|
-
return
|
|
4289
|
+
return;
|
|
4321
4290
|
}
|
|
4322
4291
|
|
|
4323
4292
|
const modelsMap = getModelsMapForPopulate(model, docs, populateOptions);
|
|
4324
|
-
|
|
4325
4293
|
if (modelsMap instanceof MongooseError) {
|
|
4326
|
-
|
|
4327
|
-
callback(modelsMap);
|
|
4328
|
-
});
|
|
4294
|
+
throw modelsMap;
|
|
4329
4295
|
}
|
|
4330
4296
|
const len = modelsMap.length;
|
|
4331
4297
|
let vals = [];
|
|
@@ -4335,7 +4301,6 @@ function populate(model, docs, options, callback) {
|
|
|
4335
4301
|
return undefined !== item;
|
|
4336
4302
|
}
|
|
4337
4303
|
|
|
4338
|
-
let _remaining = len;
|
|
4339
4304
|
let hasOne = false;
|
|
4340
4305
|
const params = [];
|
|
4341
4306
|
for (let i = 0; i < len; ++i) {
|
|
@@ -4366,7 +4331,6 @@ function populate(model, docs, options, callback) {
|
|
|
4366
4331
|
// Ensure that we set to 0 or empty array even
|
|
4367
4332
|
// if we don't actually execute a query to make sure there's a value
|
|
4368
4333
|
// and we know this path was populated for future sets. See gh-7731, gh-8230
|
|
4369
|
-
--_remaining;
|
|
4370
4334
|
_assign(model, [], mod, assignmentOpts);
|
|
4371
4335
|
continue;
|
|
4372
4336
|
}
|
|
@@ -4397,64 +4361,50 @@ function populate(model, docs, options, callback) {
|
|
|
4397
4361
|
} else if (mod.options.limit != null) {
|
|
4398
4362
|
assignmentOpts.originalLimit = mod.options.limit;
|
|
4399
4363
|
}
|
|
4400
|
-
params.push([mod, match, select, assignmentOpts
|
|
4364
|
+
params.push([mod, match, select, assignmentOpts]);
|
|
4401
4365
|
}
|
|
4402
4366
|
if (!hasOne) {
|
|
4403
4367
|
// If models but no docs, skip further deep populate.
|
|
4404
4368
|
if (modelsMap.length !== 0) {
|
|
4405
|
-
return
|
|
4369
|
+
return;
|
|
4406
4370
|
}
|
|
4407
|
-
// If no models to populate but we have a nested populate,
|
|
4408
|
-
//
|
|
4371
|
+
// If no models and no docs to populate but we have a nested populate,
|
|
4372
|
+
// probably a case of unnecessarily populating a non-ref path re: gh-8946
|
|
4409
4373
|
if (populateOptions.populate != null) {
|
|
4410
4374
|
const opts = utils.populate(populateOptions.populate).map(pop => Object.assign({}, pop, {
|
|
4411
4375
|
path: populateOptions.path + '.' + pop.path
|
|
4412
4376
|
}));
|
|
4413
|
-
model.populate(docs, opts)
|
|
4414
|
-
return;
|
|
4377
|
+
return model.populate(docs, opts);
|
|
4415
4378
|
}
|
|
4416
|
-
return
|
|
4379
|
+
return;
|
|
4417
4380
|
}
|
|
4418
4381
|
|
|
4382
|
+
const promises = [];
|
|
4419
4383
|
for (const arr of params) {
|
|
4420
|
-
_execPopulateQuery.apply(null, arr);
|
|
4421
|
-
}
|
|
4422
|
-
function _next(err, valsFromDb) {
|
|
4423
|
-
if (err != null) {
|
|
4424
|
-
return callback(err, null);
|
|
4425
|
-
}
|
|
4426
|
-
vals = vals.concat(valsFromDb);
|
|
4427
|
-
if (--_remaining === 0) {
|
|
4428
|
-
_done();
|
|
4429
|
-
}
|
|
4384
|
+
promises.push(_execPopulateQuery.apply(null, arr).then(valsFromDb => { vals = vals.concat(valsFromDb); }));
|
|
4430
4385
|
}
|
|
4431
4386
|
|
|
4432
|
-
|
|
4433
|
-
for (const arr of params) {
|
|
4434
|
-
const mod = arr[0];
|
|
4435
|
-
const assignmentOpts = arr[3];
|
|
4436
|
-
for (const val of vals) {
|
|
4437
|
-
mod.options._childDocs.push(val);
|
|
4438
|
-
}
|
|
4439
|
-
try {
|
|
4440
|
-
_assign(model, vals, mod, assignmentOpts);
|
|
4441
|
-
} catch (err) {
|
|
4442
|
-
return callback(err);
|
|
4443
|
-
}
|
|
4444
|
-
}
|
|
4387
|
+
await Promise.all(promises);
|
|
4445
4388
|
|
|
4446
|
-
|
|
4447
|
-
|
|
4389
|
+
for (const arr of params) {
|
|
4390
|
+
const mod = arr[0];
|
|
4391
|
+
const assignmentOpts = arr[3];
|
|
4392
|
+
for (const val of vals) {
|
|
4393
|
+
mod.options._childDocs.push(val);
|
|
4448
4394
|
}
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4395
|
+
_assign(model, vals, mod, assignmentOpts);
|
|
4396
|
+
}
|
|
4397
|
+
|
|
4398
|
+
for (const arr of params) {
|
|
4399
|
+
removeDeselectedForeignField(arr[0].foreignField, arr[0].options, vals);
|
|
4400
|
+
}
|
|
4401
|
+
for (const arr of params) {
|
|
4402
|
+
const mod = arr[0];
|
|
4403
|
+
if (mod.options && mod.options.options && mod.options.options._leanTransform) {
|
|
4404
|
+
for (const doc of vals) {
|
|
4405
|
+
mod.options.options._leanTransform(doc);
|
|
4455
4406
|
}
|
|
4456
4407
|
}
|
|
4457
|
-
callback();
|
|
4458
4408
|
}
|
|
4459
4409
|
}
|
|
4460
4410
|
|
|
@@ -4462,7 +4412,7 @@ function populate(model, docs, options, callback) {
|
|
|
4462
4412
|
* ignore
|
|
4463
4413
|
*/
|
|
4464
4414
|
|
|
4465
|
-
function _execPopulateQuery(mod, match, select
|
|
4415
|
+
function _execPopulateQuery(mod, match, select) {
|
|
4466
4416
|
let subPopulate = clone(mod.options.populate);
|
|
4467
4417
|
const queryOptions = Object.assign({
|
|
4468
4418
|
skip: mod.options.skip,
|
|
@@ -4528,15 +4478,12 @@ function _execPopulateQuery(mod, match, select, assignmentOpts, callback) {
|
|
|
4528
4478
|
query.populate(subPopulate);
|
|
4529
4479
|
}
|
|
4530
4480
|
|
|
4531
|
-
query.exec().then(
|
|
4481
|
+
return query.exec().then(
|
|
4532
4482
|
docs => {
|
|
4533
4483
|
for (const val of docs) {
|
|
4534
4484
|
leanPopulateMap.set(val, mod.model);
|
|
4535
4485
|
}
|
|
4536
|
-
|
|
4537
|
-
},
|
|
4538
|
-
err => {
|
|
4539
|
-
callback(err);
|
|
4486
|
+
return docs;
|
|
4540
4487
|
}
|
|
4541
4488
|
);
|
|
4542
4489
|
}
|
|
@@ -4934,6 +4881,23 @@ Model.inspect = function() {
|
|
|
4934
4881
|
return `Model { ${this.modelName} }`;
|
|
4935
4882
|
};
|
|
4936
4883
|
|
|
4884
|
+
/**
|
|
4885
|
+
* Return the MongoDB namespace for this model as a string. The namespace is the database name, followed by '.', followed by the collection name.
|
|
4886
|
+
*
|
|
4887
|
+
* #### Example:
|
|
4888
|
+
*
|
|
4889
|
+
* const conn = mongoose.createConnection('mongodb://127.0.0.1:27017/mydb');
|
|
4890
|
+
* const TestModel = conn.model('Test', mongoose.Schema({ name: String }));
|
|
4891
|
+
*
|
|
4892
|
+
* TestModel.namespace(); // 'mydb.tests'
|
|
4893
|
+
*
|
|
4894
|
+
* @api public
|
|
4895
|
+
*/
|
|
4896
|
+
|
|
4897
|
+
Model.namespace = function namespace() {
|
|
4898
|
+
return this.db.name + '.' + this.collection.collectionName;
|
|
4899
|
+
};
|
|
4900
|
+
|
|
4937
4901
|
if (util.inspect.custom) {
|
|
4938
4902
|
// Avoid Node deprecation warning DEP0079
|
|
4939
4903
|
Model[util.inspect.custom] = Model.inspect;
|
package/lib/mongoose.js
CHANGED
|
@@ -245,7 +245,7 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
|
|
|
245
245
|
* @api public
|
|
246
246
|
*/
|
|
247
247
|
|
|
248
|
-
Mongoose.prototype.set = function(key, value) {
|
|
248
|
+
Mongoose.prototype.set = function getsetOptions(key, value) {
|
|
249
249
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
250
250
|
|
|
251
251
|
if (arguments.length === 1 && typeof key !== 'object') {
|
|
@@ -376,7 +376,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
|
|
376
376
|
* @api public
|
|
377
377
|
*/
|
|
378
378
|
|
|
379
|
-
Mongoose.prototype.createConnection = function(uri, options) {
|
|
379
|
+
Mongoose.prototype.createConnection = function createConnection(uri, options) {
|
|
380
380
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
381
381
|
|
|
382
382
|
const Connection = _mongoose.__driver.Connection;
|
|
@@ -427,7 +427,6 @@ Mongoose.prototype.createConnection = function(uri, options) {
|
|
|
427
427
|
* @param {Number} [options.socketTimeoutMS=0] 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. `socketTimeoutMS` defaults to 0, which means Node.js will not time out the socket due to inactivity. 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.
|
|
428
428
|
* @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.
|
|
429
429
|
* @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
|
430
|
-
* @param {Function} [callback]
|
|
431
430
|
* @see Mongoose#createConnection https://mongoosejs.com/docs/api/mongoose.html#Mongoose.prototype.createConnection()
|
|
432
431
|
* @api public
|
|
433
432
|
* @return {Promise} resolves to `this` if connection succeeded
|
|
@@ -479,12 +478,11 @@ Mongoose.prototype.disconnect = async function disconnect() {
|
|
|
479
478
|
*
|
|
480
479
|
* @param {Object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/4.9/classes/MongoClient.html#startSession)
|
|
481
480
|
* @param {Boolean} [options.causalConsistency=true] set to false to disable causal consistency
|
|
482
|
-
* @param {Function} [callback]
|
|
483
481
|
* @return {Promise<ClientSession>} promise that resolves to a MongoDB driver `ClientSession`
|
|
484
482
|
* @api public
|
|
485
483
|
*/
|
|
486
484
|
|
|
487
|
-
Mongoose.prototype.startSession = function() {
|
|
485
|
+
Mongoose.prototype.startSession = function startSession() {
|
|
488
486
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
489
487
|
|
|
490
488
|
return _mongoose.connection.startSession.apply(_mongoose.connection, arguments);
|
|
@@ -498,7 +496,7 @@ Mongoose.prototype.startSession = function() {
|
|
|
498
496
|
* @api public
|
|
499
497
|
*/
|
|
500
498
|
|
|
501
|
-
Mongoose.prototype.pluralize = function(fn) {
|
|
499
|
+
Mongoose.prototype.pluralize = function pluralize(fn) {
|
|
502
500
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
503
501
|
|
|
504
502
|
if (arguments.length > 0) {
|
|
@@ -561,7 +559,7 @@ Mongoose.prototype.pluralize = function(fn) {
|
|
|
561
559
|
* @api public
|
|
562
560
|
*/
|
|
563
561
|
|
|
564
|
-
Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
562
|
+
Mongoose.prototype.model = function model(name, schema, collection, options) {
|
|
565
563
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
566
564
|
|
|
567
565
|
if (typeof schema === 'string') {
|
|
@@ -572,7 +570,7 @@ Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
|
572
570
|
if (arguments.length === 1) {
|
|
573
571
|
const model = _mongoose.models[name];
|
|
574
572
|
if (!model) {
|
|
575
|
-
throw new
|
|
573
|
+
throw new _mongoose.Error.MissingSchemaError(name);
|
|
576
574
|
}
|
|
577
575
|
return model;
|
|
578
576
|
}
|
|
@@ -581,7 +579,7 @@ Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
|
581
579
|
schema = new Schema(schema);
|
|
582
580
|
}
|
|
583
581
|
if (schema && !(schema instanceof Schema)) {
|
|
584
|
-
throw new Error('The 2nd parameter to `mongoose.model()` should be a ' +
|
|
582
|
+
throw new _mongoose.Error('The 2nd parameter to `mongoose.model()` should be a ' +
|
|
585
583
|
'schema or a POJO');
|
|
586
584
|
}
|
|
587
585
|
|
|
@@ -632,7 +630,7 @@ Mongoose.prototype.model = function(name, schema, collection, options) {
|
|
|
632
630
|
* ignore
|
|
633
631
|
*/
|
|
634
632
|
|
|
635
|
-
Mongoose.prototype._model = function(name, schema, collection, options) {
|
|
633
|
+
Mongoose.prototype._model = function _model(name, schema, collection, options) {
|
|
636
634
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
637
635
|
|
|
638
636
|
let model;
|
|
@@ -707,7 +705,7 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
|
|
|
707
705
|
* @return {Mongoose} this
|
|
708
706
|
*/
|
|
709
707
|
|
|
710
|
-
Mongoose.prototype.deleteModel = function(name) {
|
|
708
|
+
Mongoose.prototype.deleteModel = function deleteModel(name) {
|
|
711
709
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
712
710
|
|
|
713
711
|
_mongoose.connection.deleteModel(name);
|
|
@@ -726,7 +724,7 @@ Mongoose.prototype.deleteModel = function(name) {
|
|
|
726
724
|
* @return {Array}
|
|
727
725
|
*/
|
|
728
726
|
|
|
729
|
-
Mongoose.prototype.modelNames = function() {
|
|
727
|
+
Mongoose.prototype.modelNames = function modelNames() {
|
|
730
728
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
731
729
|
|
|
732
730
|
const names = Object.keys(_mongoose.models);
|
|
@@ -740,7 +738,7 @@ Mongoose.prototype.modelNames = function() {
|
|
|
740
738
|
* @api private
|
|
741
739
|
*/
|
|
742
740
|
|
|
743
|
-
Mongoose.prototype._applyPlugins = function(schema, options) {
|
|
741
|
+
Mongoose.prototype._applyPlugins = function _applyPlugins(schema, options) {
|
|
744
742
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
745
743
|
|
|
746
744
|
options = options || {};
|
|
@@ -763,7 +761,7 @@ Mongoose.prototype._applyPlugins = function(schema, options) {
|
|
|
763
761
|
* @api public
|
|
764
762
|
*/
|
|
765
763
|
|
|
766
|
-
Mongoose.prototype.plugin = function(fn, opts) {
|
|
764
|
+
Mongoose.prototype.plugin = function plugin(fn, opts) {
|
|
767
765
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
768
766
|
|
|
769
767
|
_mongoose.plugins.push([fn, opts]);
|
|
@@ -987,6 +985,7 @@ Mongoose.prototype.VirtualType = VirtualType;
|
|
|
987
985
|
* - [ObjectId](https://mongoosejs.com/docs/schematypes.html#objectids)
|
|
988
986
|
* - [Map](https://mongoosejs.com/docs/schematypes.html#maps)
|
|
989
987
|
* - [Subdocument](https://mongoosejs.com/docs/schematypes.html#schemas)
|
|
988
|
+
* - [Int32](https://mongoosejs.com/docs/schematypes.html#int32)
|
|
990
989
|
*
|
|
991
990
|
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
|
|
992
991
|
*
|
|
@@ -1072,7 +1071,7 @@ Mongoose.prototype.ObjectId = SchemaTypes.ObjectId;
|
|
|
1072
1071
|
* @api public
|
|
1073
1072
|
*/
|
|
1074
1073
|
|
|
1075
|
-
Mongoose.prototype.isValidObjectId = function(v) {
|
|
1074
|
+
Mongoose.prototype.isValidObjectId = function isValidObjectId(v) {
|
|
1076
1075
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
1077
1076
|
return _mongoose.Types.ObjectId.isValid(v);
|
|
1078
1077
|
};
|
|
@@ -1104,7 +1103,7 @@ Mongoose.prototype.isValidObjectId = function(v) {
|
|
|
1104
1103
|
* @api public
|
|
1105
1104
|
*/
|
|
1106
1105
|
|
|
1107
|
-
Mongoose.prototype.isObjectIdOrHexString = function(v) {
|
|
1106
|
+
Mongoose.prototype.isObjectIdOrHexString = function isObjectIdOrHexString(v) {
|
|
1108
1107
|
return isBsonType(v, 'ObjectId') || (typeof v === 'string' && objectIdHexRegexp.test(v));
|
|
1109
1108
|
};
|
|
1110
1109
|
|
|
@@ -1116,7 +1115,7 @@ Mongoose.prototype.isObjectIdOrHexString = function(v) {
|
|
|
1116
1115
|
* @param {Boolean} options.continueOnError `false` by default. If set to `true`, mongoose will not throw an error if one model syncing failed, and will return an object where the keys are the names of the models, and the values are the results/errors for each model.
|
|
1117
1116
|
* @return {Promise} Returns a Promise, when the Promise resolves the value is a list of the dropped indexes.
|
|
1118
1117
|
*/
|
|
1119
|
-
Mongoose.prototype.syncIndexes = function(options) {
|
|
1118
|
+
Mongoose.prototype.syncIndexes = function syncIndexes(options) {
|
|
1120
1119
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
1121
1120
|
return _mongoose.connection.syncIndexes(options);
|
|
1122
1121
|
};
|
|
@@ -1138,6 +1137,7 @@ Mongoose.prototype.syncIndexes = function(options) {
|
|
|
1138
1137
|
|
|
1139
1138
|
Mongoose.prototype.Decimal128 = SchemaTypes.Decimal128;
|
|
1140
1139
|
|
|
1140
|
+
|
|
1141
1141
|
/**
|
|
1142
1142
|
* The Mongoose Mixed [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for
|
|
1143
1143
|
* declaring paths in your schema that Mongoose's change tracking, casting,
|
|
@@ -1190,8 +1190,8 @@ Mongoose.prototype.Number = SchemaTypes.Number;
|
|
|
1190
1190
|
* @api public
|
|
1191
1191
|
*/
|
|
1192
1192
|
|
|
1193
|
-
Mongoose.prototype.Error =
|
|
1194
|
-
Mongoose.prototype.MongooseError =
|
|
1193
|
+
Mongoose.prototype.Error = MongooseError;
|
|
1194
|
+
Mongoose.prototype.MongooseError = MongooseError;
|
|
1195
1195
|
|
|
1196
1196
|
/**
|
|
1197
1197
|
* Mongoose uses this function to get the current time when setting
|
|
@@ -1216,7 +1216,7 @@ Mongoose.prototype.now = function now() { return new Date(); };
|
|
|
1216
1216
|
* @api public
|
|
1217
1217
|
*/
|
|
1218
1218
|
|
|
1219
|
-
Mongoose.prototype.CastError =
|
|
1219
|
+
Mongoose.prototype.CastError = MongooseError.CastError;
|
|
1220
1220
|
|
|
1221
1221
|
/**
|
|
1222
1222
|
* The constructor used for schematype options
|
package/lib/query.js
CHANGED
|
@@ -2381,6 +2381,7 @@ Query.prototype._find = async function _find() {
|
|
|
2381
2381
|
_completeManyLean(_this.model.schema, docs, null, completeManyOptions) :
|
|
2382
2382
|
_this._completeMany(docs, fields, userProvidedFields, completeManyOptions);
|
|
2383
2383
|
}
|
|
2384
|
+
|
|
2384
2385
|
const pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions);
|
|
2385
2386
|
|
|
2386
2387
|
if (mongooseOptions.lean) {
|
|
@@ -3196,7 +3197,6 @@ Query.prototype.deleteMany = function(filter, options) {
|
|
|
3196
3197
|
/**
|
|
3197
3198
|
* Execute a `deleteMany()` query
|
|
3198
3199
|
*
|
|
3199
|
-
* @param {Function} callback
|
|
3200
3200
|
* @method _deleteMany
|
|
3201
3201
|
* @instance
|
|
3202
3202
|
* @memberOf Query
|
|
@@ -3489,13 +3489,6 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() {
|
|
|
3489
3489
|
* - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
|
|
3490
3490
|
* - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
|
|
3491
3491
|
*
|
|
3492
|
-
* #### Callback Signature
|
|
3493
|
-
*
|
|
3494
|
-
* function(error, doc) {
|
|
3495
|
-
* // error: any errors that occurred
|
|
3496
|
-
* // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
|
|
3497
|
-
* }
|
|
3498
|
-
*
|
|
3499
3492
|
* #### Example:
|
|
3500
3493
|
*
|
|
3501
3494
|
* A.where().findOneAndDelete(conditions, options) // return Query
|
|
@@ -3586,13 +3579,6 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() {
|
|
|
3586
3579
|
* - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
|
|
3587
3580
|
* - `includeResultMetadata`: if true, returns the full [ModifyResult from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/ModifyResult.html) rather than just the document
|
|
3588
3581
|
*
|
|
3589
|
-
* #### Callback Signature
|
|
3590
|
-
*
|
|
3591
|
-
* function(error, doc) {
|
|
3592
|
-
* // error: any errors that occurred
|
|
3593
|
-
* // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
|
|
3594
|
-
* }
|
|
3595
|
-
*
|
|
3596
3582
|
* #### Example:
|
|
3597
3583
|
*
|
|
3598
3584
|
* A.where().findOneAndReplace(filter, replacement, options); // return Query
|
|
@@ -4024,7 +4010,6 @@ Query.prototype._replaceOne = async function _replaceOne() {
|
|
|
4024
4010
|
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
|
|
4025
4011
|
* @param {Boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
|
|
4026
4012
|
* @param {Boolean} [options.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
|
|
4027
|
-
* @param {Function} [callback] params are (error, writeOpResult)
|
|
4028
4013
|
* @return {Query} this
|
|
4029
4014
|
* @see Model.update https://mongoosejs.com/docs/api/model.html#Model.update()
|
|
4030
4015
|
* @see Query docs https://mongoosejs.com/docs/queries.html
|
|
@@ -4095,7 +4080,6 @@ Query.prototype.updateMany = function(conditions, doc, options, callback) {
|
|
|
4095
4080
|
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
|
|
4096
4081
|
* @param {Boolean} [options.overwriteDiscriminatorKey=false] Mongoose removes discriminator key updates from `update` by default, set `overwriteDiscriminatorKey` to `true` to allow updating the discriminator key
|
|
4097
4082
|
* @param {Boolean} [options.overwriteImmutable=false] Mongoose removes updated immutable properties from `update` by default (excluding $setOnInsert). Set `overwriteImmutable` to `true` to allow updating immutable properties using other update operators.
|
|
4098
|
-
* @param {Function} [callback] params are (error, writeOpResult)
|
|
4099
4083
|
* @return {Query} this
|
|
4100
4084
|
* @see Model.update https://mongoosejs.com/docs/api/model.html#Model.update()
|
|
4101
4085
|
* @see Query docs https://mongoosejs.com/docs/queries.html
|
|
@@ -4162,7 +4146,6 @@ Query.prototype.updateOne = function(conditions, doc, options, callback) {
|
|
|
4162
4146
|
* @param {Object} [options.writeConcern=null] sets the [write concern](https://www.mongodb.com/docs/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](https://mongoosejs.com/docs/guide.html#writeConcern)
|
|
4163
4147
|
* @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](https://mongoosejs.com/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
|
|
4164
4148
|
* @param {Boolean} [options.translateAliases=null] If set to `true`, translates any schema-defined aliases in `filter`, `projection`, `update`, and `distinct`. Throws an error if there are any conflicts where both alias and raw property are defined on the same object.
|
|
4165
|
-
* @param {Function} [callback] params are (error, writeOpResult)
|
|
4166
4149
|
* @return {Query} this
|
|
4167
4150
|
* @see Model.update https://mongoosejs.com/docs/api/model.html#Model.update()
|
|
4168
4151
|
* @see Query docs https://mongoosejs.com/docs/queries.html
|
|
@@ -4466,6 +4449,8 @@ Query.prototype.exec = async function exec(op) {
|
|
|
4466
4449
|
} else {
|
|
4467
4450
|
error = err;
|
|
4468
4451
|
}
|
|
4452
|
+
|
|
4453
|
+
error = this.model.schema._transformDuplicateKeyError(error);
|
|
4469
4454
|
}
|
|
4470
4455
|
|
|
4471
4456
|
res = await _executePostHooks(this, res, error);
|
|
@@ -4762,12 +4747,13 @@ Query.prototype._castUpdate = function _castUpdate(obj) {
|
|
|
4762
4747
|
*/
|
|
4763
4748
|
|
|
4764
4749
|
Query.prototype.populate = function() {
|
|
4750
|
+
const args = Array.from(arguments);
|
|
4765
4751
|
// Bail when given no truthy arguments
|
|
4766
|
-
if (!
|
|
4752
|
+
if (!args.some(Boolean)) {
|
|
4767
4753
|
return this;
|
|
4768
4754
|
}
|
|
4769
4755
|
|
|
4770
|
-
const res = utils.populate.apply(null,
|
|
4756
|
+
const res = utils.populate.apply(null, args);
|
|
4771
4757
|
|
|
4772
4758
|
// Propagate readConcern and readPreference and lean from parent query,
|
|
4773
4759
|
// unless one already specified
|
package/lib/queryHelpers.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Module dependencies
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
const PopulateOptions = require('./options/populateOptions');
|
|
7
8
|
const checkEmbeddedDiscriminatorKeyProjection =
|
|
8
9
|
require('./helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection');
|
|
9
10
|
const get = require('./helpers/get');
|
|
@@ -13,32 +14,6 @@ const isDefiningProjection = require('./helpers/projection/isDefiningProjection'
|
|
|
13
14
|
const clone = require('./helpers/clone');
|
|
14
15
|
const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
-
* Prepare a set of path options for query population.
|
|
18
|
-
*
|
|
19
|
-
* @param {Query} query
|
|
20
|
-
* @param {Object} options
|
|
21
|
-
* @return {Array}
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
exports.preparePopulationOptions = function preparePopulationOptions(query, options) {
|
|
25
|
-
const _populate = query.options.populate;
|
|
26
|
-
const pop = Object.keys(_populate).reduce((vals, key) => vals.concat([_populate[key]]), []);
|
|
27
|
-
|
|
28
|
-
// lean options should trickle through all queries
|
|
29
|
-
if (options.lean != null) {
|
|
30
|
-
pop
|
|
31
|
-
.filter(p => (p && p.options && p.options.lean) == null)
|
|
32
|
-
.forEach(makeLean(options.lean));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
pop.forEach(opts => {
|
|
36
|
-
opts._localModel = query.model;
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return pop;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
17
|
/**
|
|
43
18
|
* Prepare a set of path options for query population. This is the MongooseQuery
|
|
44
19
|
* version
|
|
@@ -73,12 +48,18 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
|
|
73
48
|
}
|
|
74
49
|
|
|
75
50
|
const projection = query._fieldsForExec();
|
|
76
|
-
pop.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
for (let i = 0; i < pop.length; ++i) {
|
|
52
|
+
if (pop[i] instanceof PopulateOptions) {
|
|
53
|
+
pop[i] = new PopulateOptions({
|
|
54
|
+
...pop[i],
|
|
55
|
+
_queryProjection: projection,
|
|
56
|
+
_localModel: query.model
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
pop[i]._queryProjection = projection;
|
|
60
|
+
pop[i]._localModel = query.model;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
82
63
|
|
|
83
64
|
return pop;
|
|
84
65
|
};
|
package/lib/schema/bigint.js
CHANGED
|
@@ -81,12 +81,12 @@ SchemaBigInt.setters = [];
|
|
|
81
81
|
SchemaBigInt.get = SchemaType.get;
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Get/set the function used to cast arbitrary values to
|
|
84
|
+
* Get/set the function used to cast arbitrary values to bigints.
|
|
85
85
|
*
|
|
86
86
|
* #### Example:
|
|
87
87
|
*
|
|
88
88
|
* // Make Mongoose cast empty string '' to false.
|
|
89
|
-
* const original = mongoose.Schema.BigInt.cast();
|
|
89
|
+
* const original = mongoose.Schema.Types.BigInt.cast();
|
|
90
90
|
* mongoose.Schema.BigInt.cast(v => {
|
|
91
91
|
* if (v === '') {
|
|
92
92
|
* return false;
|