mongoose 6.2.6 → 6.2.9
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 +35 -26
- package/CHANGELOG.md +30 -0
- package/dist/browser.umd.js +83 -75
- package/lib/browserDocument.js +1 -0
- package/lib/connection.js +4 -4
- package/lib/cursor/AggregationCursor.js +0 -1
- package/lib/cursor/QueryCursor.js +2 -1
- package/lib/document.js +49 -11
- package/lib/helpers/document/handleSpreadDoc.js +19 -1
- package/lib/helpers/query/castFilterPath.js +0 -1
- package/lib/index.js +1 -3
- package/lib/model.js +78 -67
- package/lib/options/SchemaDateOptions.js +8 -1
- package/lib/query.js +41 -13
- package/lib/queryhelpers.js +17 -0
- package/lib/schema/SubdocumentPath.js +4 -1
- package/lib/schema/array.js +1 -0
- package/lib/schema/documentarray.js +14 -7
- package/lib/schema.js +14 -4
- package/lib/schematype.js +3 -1
- package/lib/types/array/methods/index.js +2 -0
- package/lib/virtualtype.js +1 -0
- package/package.json +12 -11
- package/tools/repl.js +8 -8
- package/tools/sharded.js +3 -3
- package/types/connection.d.ts +116 -116
- package/types/document.d.ts +3 -0
- package/types/error.d.ts +2 -2
- package/types/index.d.ts +73 -178
- package/types/mongooseoptions.d.ts +180 -0
- package/types/pipelinestage.d.ts +194 -194
- package/types/schemaoptions.d.ts +8 -2
package/lib/browserDocument.js
CHANGED
|
@@ -17,6 +17,7 @@ const isObject = require('./helpers/isObject');
|
|
|
17
17
|
* Document constructor.
|
|
18
18
|
*
|
|
19
19
|
* @param {Object} obj the values to set
|
|
20
|
+
* @param {Object} schema
|
|
20
21
|
* @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data
|
|
21
22
|
* @param {Boolean} [skipId] bool, should we auto create an ObjectId _id
|
|
22
23
|
* @inherits NodeJS EventEmitter https://nodejs.org/api/events.html#events_class_events_eventemitter
|
package/lib/connection.js
CHANGED
|
@@ -788,10 +788,6 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
788
788
|
}
|
|
789
789
|
_this.client = client;
|
|
790
790
|
|
|
791
|
-
for (const db of this.otherDbs) {
|
|
792
|
-
_setClient(db, client, {}, db.name);
|
|
793
|
-
}
|
|
794
|
-
|
|
795
791
|
client.setMaxListeners(0);
|
|
796
792
|
client.connect((error) => {
|
|
797
793
|
if (error) {
|
|
@@ -800,6 +796,10 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
|
|
800
796
|
|
|
801
797
|
_setClient(_this, client, options, dbName);
|
|
802
798
|
|
|
799
|
+
for (const db of this.otherDbs) {
|
|
800
|
+
_setClient(db, client, {}, db.name);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
803
|
resolve(_this);
|
|
804
804
|
});
|
|
805
805
|
});
|
|
@@ -26,7 +26,6 @@ const util = require('util');
|
|
|
26
26
|
* Use [`Aggregate#cursor()`](/docs/api.html#aggregate_Aggregate-cursor) instead.
|
|
27
27
|
*
|
|
28
28
|
* @param {Aggregate} agg
|
|
29
|
-
* @param {Object} options
|
|
30
29
|
* @inherits Readable
|
|
31
30
|
* @event `cursor`: Emitted when the cursor is created
|
|
32
31
|
* @event `error`: Emitted when an error occurred
|
|
@@ -472,7 +472,8 @@ function _nextDoc(ctx, doc, pop, callback) {
|
|
|
472
472
|
});
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
|
|
475
|
+
const { model, _fields, _userProvidedFields, options } = ctx.query;
|
|
476
|
+
helpers.createModelAndInit(model, doc, _fields, _userProvidedFields, options, pop, (err, doc) => {
|
|
476
477
|
if (err != null) {
|
|
477
478
|
return callback(err);
|
|
478
479
|
}
|
package/lib/document.js
CHANGED
|
@@ -156,9 +156,9 @@ function Document(obj, fields, skipId, options) {
|
|
|
156
156
|
if (obj) {
|
|
157
157
|
// Skip set hooks
|
|
158
158
|
if (this.$__original_set) {
|
|
159
|
-
this.$__original_set(obj, undefined, true);
|
|
159
|
+
this.$__original_set(obj, undefined, true, options);
|
|
160
160
|
} else {
|
|
161
|
-
this.$set(obj, undefined, true);
|
|
161
|
+
this.$set(obj, undefined, true, options);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
if (obj instanceof Document) {
|
|
@@ -801,7 +801,7 @@ function init(self, obj, doc, opts, prefix) {
|
|
|
801
801
|
init(self, obj[i], doc[i], opts, path + '.');
|
|
802
802
|
} else if (!schemaType) {
|
|
803
803
|
doc[i] = obj[i];
|
|
804
|
-
if (!strict) {
|
|
804
|
+
if (!strict && !prefix) {
|
|
805
805
|
self[i] = obj[i];
|
|
806
806
|
}
|
|
807
807
|
} else {
|
|
@@ -1836,6 +1836,7 @@ Document.prototype.$__path = function(path) {
|
|
|
1836
1836
|
*/
|
|
1837
1837
|
|
|
1838
1838
|
Document.prototype.markModified = function(path, scope) {
|
|
1839
|
+
// console.log('MarkModified', path, new Error().stack);
|
|
1839
1840
|
this.$__.activePaths.modify(path);
|
|
1840
1841
|
if (scope != null && !this.$isSubdocument) {
|
|
1841
1842
|
this.$__.pathsToScopes = this.$__pathsToScopes || {};
|
|
@@ -2422,6 +2423,7 @@ Document.prototype.validate = function(pathsToValidate, options, callback) {
|
|
|
2422
2423
|
|
|
2423
2424
|
this.$__validate(pathsToValidate, options, (error) => {
|
|
2424
2425
|
this.$op = null;
|
|
2426
|
+
this.$__.validating = null;
|
|
2425
2427
|
cb(error);
|
|
2426
2428
|
});
|
|
2427
2429
|
}, this.constructor.events);
|
|
@@ -2472,7 +2474,6 @@ function _getPathsToValidate(doc) {
|
|
|
2472
2474
|
return true;
|
|
2473
2475
|
}));
|
|
2474
2476
|
|
|
2475
|
-
|
|
2476
2477
|
Object.keys(doc.$__.activePaths.states.init).forEach(addToPaths);
|
|
2477
2478
|
Object.keys(doc.$__.activePaths.states.modify).forEach(addToPaths);
|
|
2478
2479
|
Object.keys(doc.$__.activePaths.states.default).forEach(addToPaths);
|
|
@@ -2484,28 +2485,53 @@ function _getPathsToValidate(doc) {
|
|
|
2484
2485
|
if (subdoc.$basePath) {
|
|
2485
2486
|
// Remove child paths for now, because we'll be validating the whole
|
|
2486
2487
|
// subdoc
|
|
2488
|
+
if (!subdoc.$__.fullPath) {
|
|
2489
|
+
subdoc.ownerDocument();
|
|
2490
|
+
}
|
|
2491
|
+
const fullPathToSubdoc = subdoc.$__.fullPath;
|
|
2492
|
+
|
|
2487
2493
|
for (const p of paths) {
|
|
2488
|
-
if (p === null || p.startsWith(
|
|
2494
|
+
if (p === null || p.startsWith(fullPathToSubdoc + '.')) {
|
|
2489
2495
|
paths.delete(p);
|
|
2490
2496
|
}
|
|
2491
2497
|
}
|
|
2492
2498
|
|
|
2493
|
-
if (doc.$isModified(
|
|
2494
|
-
!doc.isDirectModified(
|
|
2495
|
-
!doc.$isDefault(
|
|
2496
|
-
paths.add(
|
|
2499
|
+
if (doc.$isModified(fullPathToSubdoc, modifiedPaths) &&
|
|
2500
|
+
!doc.isDirectModified(fullPathToSubdoc) &&
|
|
2501
|
+
!doc.$isDefault(fullPathToSubdoc)) {
|
|
2502
|
+
paths.add(fullPathToSubdoc);
|
|
2497
2503
|
|
|
2498
|
-
skipSchemaValidators[
|
|
2504
|
+
skipSchemaValidators[fullPathToSubdoc] = true;
|
|
2499
2505
|
}
|
|
2500
2506
|
}
|
|
2501
2507
|
}
|
|
2502
2508
|
|
|
2509
|
+
for (const path of paths) {
|
|
2510
|
+
const _pathType = doc.$__schema.path(path);
|
|
2511
|
+
if (!_pathType) {
|
|
2512
|
+
continue;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
// Optimization: if primitive path with no validators, or array of primitives
|
|
2516
|
+
// with no validators, skip validating this path entirely.
|
|
2517
|
+
if (!_pathType.caster && _pathType.validators.length === 0) {
|
|
2518
|
+
paths.delete(path);
|
|
2519
|
+
} else if (_pathType.$isMongooseArray &&
|
|
2520
|
+
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
2521
|
+
!_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
|
|
2522
|
+
_pathType.validators.length === 0 && // and arrays with top-level validators
|
|
2523
|
+
_pathType.$embeddedSchemaType.validators.length === 0) {
|
|
2524
|
+
paths.delete(path);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2503
2528
|
// from here on we're not removing items from paths
|
|
2504
2529
|
|
|
2505
2530
|
// gh-661: if a whole array is modified, make sure to run validation on all
|
|
2506
2531
|
// the children as well
|
|
2507
2532
|
for (const path of paths) {
|
|
2508
2533
|
const _pathType = doc.$__schema.path(path);
|
|
2534
|
+
|
|
2509
2535
|
if (!_pathType ||
|
|
2510
2536
|
!_pathType.$isMongooseArray ||
|
|
2511
2537
|
// To avoid potential performance issues, skip doc arrays whose children
|
|
@@ -2517,6 +2543,16 @@ function _getPathsToValidate(doc) {
|
|
|
2517
2543
|
continue;
|
|
2518
2544
|
}
|
|
2519
2545
|
|
|
2546
|
+
// gh-11380: optimization. If the array isn't a document array and there's no validators
|
|
2547
|
+
// on the array type, there's no need to run validation on the individual array elements.
|
|
2548
|
+
if (_pathType &&
|
|
2549
|
+
_pathType.$isMongooseArray &&
|
|
2550
|
+
!_pathType.$isMongooseDocumentArray && // Skip document arrays...
|
|
2551
|
+
!_pathType.$embeddedSchemaType.$isMongooseArray && // and arrays of arrays
|
|
2552
|
+
_pathType.$embeddedSchemaType.validators.length === 0) {
|
|
2553
|
+
continue;
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2520
2556
|
const val = doc.$__getValue(path);
|
|
2521
2557
|
_pushNestedArrayPaths(val, paths, path);
|
|
2522
2558
|
}
|
|
@@ -2602,7 +2638,8 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
|
|
|
2602
2638
|
const _this = this;
|
|
2603
2639
|
const _complete = () => {
|
|
2604
2640
|
let validationError = this.$__.validationError;
|
|
2605
|
-
this.$__.validationError =
|
|
2641
|
+
this.$__.validationError = null;
|
|
2642
|
+
this.$__.validating = null;
|
|
2606
2643
|
|
|
2607
2644
|
if (shouldValidateModifiedOnly && validationError != null) {
|
|
2608
2645
|
// Remove any validation errors that aren't from modified paths
|
|
@@ -2648,6 +2685,7 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
|
|
|
2648
2685
|
} else if (pathsToSkip) {
|
|
2649
2686
|
paths = _handlePathsToSkip(paths, pathsToSkip);
|
|
2650
2687
|
}
|
|
2688
|
+
|
|
2651
2689
|
if (paths.length === 0) {
|
|
2652
2690
|
return immediate(function() {
|
|
2653
2691
|
const error = _complete();
|
|
@@ -2,14 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
const utils = require('../../utils');
|
|
4
4
|
|
|
5
|
+
const keysToSkip = new Set(['__index', '__parentArray', '_doc']);
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Using spread operator on a Mongoose document gives you a
|
|
7
9
|
* POJO that has a tendency to cause infinite recursion. So
|
|
8
10
|
* we use this function on `set()` to prevent that.
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
|
-
module.exports = function handleSpreadDoc(v) {
|
|
13
|
+
module.exports = function handleSpreadDoc(v, includeExtraKeys) {
|
|
12
14
|
if (utils.isPOJO(v) && v.$__ != null && v._doc != null) {
|
|
15
|
+
if (includeExtraKeys) {
|
|
16
|
+
const extraKeys = {};
|
|
17
|
+
for (const key of Object.keys(v)) {
|
|
18
|
+
if (typeof key === 'symbol') {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (key[0] === '$') {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (keysToSkip.has(key)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
extraKeys[key] = v[key];
|
|
28
|
+
}
|
|
29
|
+
return { ...v._doc, ...extraKeys };
|
|
30
|
+
}
|
|
13
31
|
return v._doc;
|
|
14
32
|
}
|
|
15
33
|
|
|
@@ -41,7 +41,6 @@ module.exports = function castFilterPath(query, schematype, val) {
|
|
|
41
41
|
}
|
|
42
42
|
continue;
|
|
43
43
|
}
|
|
44
|
-
// cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
|
|
45
44
|
} else {
|
|
46
45
|
val[$cond] = schematype.castForQueryWrapper({
|
|
47
46
|
$conditional: $cond,
|
package/lib/index.js
CHANGED
|
@@ -24,7 +24,6 @@ const legacyPluralize = require('./helpers/pluralize');
|
|
|
24
24
|
const utils = require('./utils');
|
|
25
25
|
const pkg = require('../package.json');
|
|
26
26
|
const cast = require('./cast');
|
|
27
|
-
const clearValidating = require('./plugins/clearValidating');
|
|
28
27
|
const removeSubdocs = require('./plugins/removeSubdocs');
|
|
29
28
|
const saveSubdocs = require('./plugins/saveSubdocs');
|
|
30
29
|
const trackTransaction = require('./plugins/trackTransaction');
|
|
@@ -107,8 +106,7 @@ function Mongoose(options) {
|
|
|
107
106
|
[validateBeforeSave, { deduplicate: true }],
|
|
108
107
|
[shardingPlugin, { deduplicate: true }],
|
|
109
108
|
[removeSubdocs, { deduplicate: true }],
|
|
110
|
-
[trackTransaction, { deduplicate: true }]
|
|
111
|
-
[clearValidating, { deduplicate: true }]
|
|
109
|
+
[trackTransaction, { deduplicate: true }]
|
|
112
110
|
]
|
|
113
111
|
});
|
|
114
112
|
}
|
package/lib/model.js
CHANGED
|
@@ -245,8 +245,7 @@ function _applyCustomWhere(doc, where) {
|
|
|
245
245
|
*/
|
|
246
246
|
|
|
247
247
|
Model.prototype.$__handleSave = function(options, callback) {
|
|
248
|
-
const
|
|
249
|
-
let saveOptions = {};
|
|
248
|
+
const saveOptions = {};
|
|
250
249
|
|
|
251
250
|
applyWriteConcern(this.$__schema, options);
|
|
252
251
|
if (typeof options.writeConcern !== 'undefined') {
|
|
@@ -274,14 +273,10 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
274
273
|
if ('checkKeys' in options) {
|
|
275
274
|
saveOptions.checkKeys = options.checkKeys;
|
|
276
275
|
}
|
|
277
|
-
const session = this.$session();
|
|
278
276
|
if (!saveOptions.hasOwnProperty('session')) {
|
|
279
|
-
saveOptions.session = session;
|
|
277
|
+
saveOptions.session = this.$session();
|
|
280
278
|
}
|
|
281
279
|
|
|
282
|
-
if (Object.keys(saveOptions).length === 0) {
|
|
283
|
-
saveOptions = null;
|
|
284
|
-
}
|
|
285
280
|
if (this.$isNew) {
|
|
286
281
|
// send entire doc
|
|
287
282
|
const obj = this.toObject(saveToObjectOptions);
|
|
@@ -298,9 +293,9 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
298
293
|
}
|
|
299
294
|
|
|
300
295
|
this.$__version(true, obj);
|
|
301
|
-
this[modelCollectionSymbol].insertOne(obj, saveOptions,
|
|
296
|
+
this[modelCollectionSymbol].insertOne(obj, saveOptions, (err, ret) => {
|
|
302
297
|
if (err) {
|
|
303
|
-
_setIsNew(
|
|
298
|
+
_setIsNew(this, true);
|
|
304
299
|
|
|
305
300
|
callback(err, null);
|
|
306
301
|
return;
|
|
@@ -308,64 +303,67 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
308
303
|
|
|
309
304
|
callback(null, ret);
|
|
310
305
|
});
|
|
306
|
+
|
|
311
307
|
this.$__reset();
|
|
312
308
|
_setIsNew(this, false);
|
|
313
309
|
// Make it possible to retry the insert
|
|
314
310
|
this.$__.inserting = true;
|
|
315
|
-
} else {
|
|
316
|
-
// Make sure we don't treat it as a new object on error,
|
|
317
|
-
// since it already exists
|
|
318
|
-
this.$__.inserting = false;
|
|
319
|
-
|
|
320
|
-
const delta = this.$__delta();
|
|
321
|
-
if (delta) {
|
|
322
|
-
if (delta instanceof MongooseError) {
|
|
323
|
-
callback(delta);
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
311
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
callback(where);
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
332
314
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
this.$__undoReset();
|
|
315
|
+
// Make sure we don't treat it as a new object on error,
|
|
316
|
+
// since it already exists
|
|
317
|
+
this.$__.inserting = false;
|
|
337
318
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
callback(null, ret);
|
|
343
|
-
});
|
|
344
|
-
} else {
|
|
345
|
-
const optionsWithCustomValues = Object.assign({}, options, saveOptions);
|
|
346
|
-
const where = this.$__where();
|
|
347
|
-
if (this.$__schema.options.optimisticConcurrency) {
|
|
348
|
-
const key = this.$__schema.options.versionKey;
|
|
349
|
-
const val = this.$__getValue(key);
|
|
350
|
-
if (val != null) {
|
|
351
|
-
where[key] = val;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
this.constructor.exists(where, optionsWithCustomValues)
|
|
355
|
-
.then(documentExists => {
|
|
356
|
-
const matchedCount = !documentExists ? 0 : 1;
|
|
357
|
-
callback(null, { $where: where, matchedCount });
|
|
358
|
-
})
|
|
359
|
-
.catch(callback);
|
|
319
|
+
const delta = this.$__delta();
|
|
320
|
+
if (delta) {
|
|
321
|
+
if (delta instanceof MongooseError) {
|
|
322
|
+
callback(delta);
|
|
360
323
|
return;
|
|
361
324
|
}
|
|
362
325
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
326
|
+
const where = this.$__where(delta[0]);
|
|
327
|
+
if (where instanceof MongooseError) {
|
|
328
|
+
callback(where);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
366
331
|
|
|
367
|
-
|
|
332
|
+
_applyCustomWhere(this, where);
|
|
333
|
+
this[modelCollectionSymbol].updateOne(where, delta[1], saveOptions, (err, ret) => {
|
|
334
|
+
if (err) {
|
|
335
|
+
this.$__undoReset();
|
|
336
|
+
|
|
337
|
+
callback(err);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
ret.$where = where;
|
|
341
|
+
callback(null, ret);
|
|
342
|
+
});
|
|
343
|
+
} else {
|
|
344
|
+
const optionsWithCustomValues = Object.assign({}, options, saveOptions);
|
|
345
|
+
const where = this.$__where();
|
|
346
|
+
if (this.$__schema.options.optimisticConcurrency) {
|
|
347
|
+
const key = this.$__schema.options.versionKey;
|
|
348
|
+
const val = this.$__getValue(key);
|
|
349
|
+
if (val != null) {
|
|
350
|
+
where[key] = val;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
this.constructor.exists(where, optionsWithCustomValues)
|
|
354
|
+
.then(documentExists => {
|
|
355
|
+
const matchedCount = !documentExists ? 0 : 1;
|
|
356
|
+
callback(null, { $where: where, matchedCount });
|
|
357
|
+
})
|
|
358
|
+
.catch(callback);
|
|
359
|
+
return;
|
|
368
360
|
}
|
|
361
|
+
|
|
362
|
+
// store the modified paths before the document is reset
|
|
363
|
+
this.$__.modifiedPaths = this.modifiedPaths();
|
|
364
|
+
this.$__reset();
|
|
365
|
+
|
|
366
|
+
_setIsNew(this, false);
|
|
369
367
|
};
|
|
370
368
|
|
|
371
369
|
/*!
|
|
@@ -374,8 +372,8 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
374
372
|
|
|
375
373
|
Model.prototype.$__save = function(options, callback) {
|
|
376
374
|
this.$__handleSave(options, (error, result) => {
|
|
377
|
-
const hooks = this.$__schema.s.hooks;
|
|
378
375
|
if (error) {
|
|
376
|
+
const hooks = this.$__schema.s.hooks;
|
|
379
377
|
return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
|
|
380
378
|
callback(error, this);
|
|
381
379
|
});
|
|
@@ -423,6 +421,7 @@ Model.prototype.$__save = function(options, callback) {
|
|
|
423
421
|
this.$__undoReset();
|
|
424
422
|
error = new DocumentNotFoundError(result.$where,
|
|
425
423
|
this.constructor.modelName, numAffected, result);
|
|
424
|
+
const hooks = this.$__schema.s.hooks;
|
|
426
425
|
return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
|
|
427
426
|
callback(error, this);
|
|
428
427
|
});
|
|
@@ -516,9 +515,9 @@ Model.prototype.save = function(options, fn) {
|
|
|
516
515
|
this.$__.saveOptions = options;
|
|
517
516
|
|
|
518
517
|
this.$__save(options, error => {
|
|
519
|
-
this.$__.saving =
|
|
520
|
-
|
|
521
|
-
|
|
518
|
+
this.$__.saving = null;
|
|
519
|
+
this.$__.saveOptions = null;
|
|
520
|
+
this.$__.$versionError = null;
|
|
522
521
|
this.$op = null;
|
|
523
522
|
|
|
524
523
|
if (error) {
|
|
@@ -1375,6 +1374,16 @@ Model.createCollection = function createCollection(options, callback) {
|
|
|
1375
1374
|
this.schema.options.timeseries;
|
|
1376
1375
|
if (timeseries != null) {
|
|
1377
1376
|
options = Object.assign({ timeseries }, options);
|
|
1377
|
+
if (options.expireAfterSeconds != null) {
|
|
1378
|
+
// do nothing
|
|
1379
|
+
} else if (options.expires != null) {
|
|
1380
|
+
utils.expires(options);
|
|
1381
|
+
} else if (this.schema.options.expireAfterSeconds != null) {
|
|
1382
|
+
options.expireAfterSeconds = this.schema.options.expireAfterSeconds;
|
|
1383
|
+
} else if (this.schema.options.expires != null) {
|
|
1384
|
+
options.expires = this.schema.options.expires;
|
|
1385
|
+
utils.expires(options);
|
|
1386
|
+
}
|
|
1378
1387
|
}
|
|
1379
1388
|
|
|
1380
1389
|
callback = this.$handleCallbackError(callback);
|
|
@@ -1875,7 +1884,7 @@ Model.discriminators;
|
|
|
1875
1884
|
* ####Note:
|
|
1876
1885
|
* Only translate arguments of object type anything else is returned raw
|
|
1877
1886
|
*
|
|
1878
|
-
* @param {Object}
|
|
1887
|
+
* @param {Object} fields fields/conditions that may contain aliased keys
|
|
1879
1888
|
* @return {Object} the translated 'pure' fields/conditions
|
|
1880
1889
|
*/
|
|
1881
1890
|
Model.translateAliases = function translateAliases(fields) {
|
|
@@ -2836,11 +2845,11 @@ Model.findByIdAndDelete = function(id, options, callback) {
|
|
|
2836
2845
|
*
|
|
2837
2846
|
* ####Examples:
|
|
2838
2847
|
*
|
|
2839
|
-
* A.findOneAndReplace(
|
|
2840
|
-
* A.findOneAndReplace(
|
|
2841
|
-
* A.findOneAndReplace(
|
|
2842
|
-
* A.findOneAndReplace(
|
|
2843
|
-
* A.findOneAndReplace()
|
|
2848
|
+
* A.findOneAndReplace(filter, replacement, options, callback) // executes
|
|
2849
|
+
* A.findOneAndReplace(filter, replacement, options) // return Query
|
|
2850
|
+
* A.findOneAndReplace(filter, replacement, callback) // executes
|
|
2851
|
+
* A.findOneAndReplace(filter, replacement) // returns Query
|
|
2852
|
+
* A.findOneAndReplace() // returns Query
|
|
2844
2853
|
*
|
|
2845
2854
|
* @param {Object} filter Replace the first document that matches this filter
|
|
2846
2855
|
* @param {Object} [replacement] Replace with this document
|
|
@@ -2861,8 +2870,10 @@ Model.findOneAndReplace = function(filter, replacement, options, callback) {
|
|
|
2861
2870
|
|
|
2862
2871
|
if (arguments.length === 1 && typeof filter === 'function') {
|
|
2863
2872
|
const msg = 'Model.findOneAndReplace(): First argument must not be a function.\n\n'
|
|
2864
|
-
+ ' ' + this.modelName + '.findOneAndReplace(
|
|
2865
|
-
+ ' ' + this.modelName + '.findOneAndReplace(
|
|
2873
|
+
+ ' ' + this.modelName + '.findOneAndReplace(filter, replacement, options, callback)\n'
|
|
2874
|
+
+ ' ' + this.modelName + '.findOneAndReplace(filter, replacement, callback)\n'
|
|
2875
|
+
+ ' ' + this.modelName + '.findOneAndReplace(filter, replacement)\n'
|
|
2876
|
+
+ ' ' + this.modelName + '.findOneAndReplace(filter, callback)\n'
|
|
2866
2877
|
+ ' ' + this.modelName + '.findOneAndReplace()\n';
|
|
2867
2878
|
throw new TypeError(msg);
|
|
2868
2879
|
}
|
|
@@ -48,6 +48,13 @@ Object.defineProperty(SchemaDateOptions.prototype, 'max', opts);
|
|
|
48
48
|
/**
|
|
49
49
|
* If set, Mongoose creates a TTL index on this path.
|
|
50
50
|
*
|
|
51
|
+
* mongo TTL index `expireAfterSeconds` value will take 'expires' value expressed in seconds.
|
|
52
|
+
*
|
|
53
|
+
* ####Example:
|
|
54
|
+
*
|
|
55
|
+
* const schema = new Schema({ "expireAt": { type: Date, expires: 11 } });
|
|
56
|
+
* // if 'expireAt' is set, then document expires at expireAt + 11 seconds
|
|
57
|
+
*
|
|
51
58
|
* @api public
|
|
52
59
|
* @property expires
|
|
53
60
|
* @memberOf SchemaDateOptions
|
|
@@ -61,4 +68,4 @@ Object.defineProperty(SchemaDateOptions.prototype, 'expires', opts);
|
|
|
61
68
|
* ignore
|
|
62
69
|
*/
|
|
63
70
|
|
|
64
|
-
module.exports = SchemaDateOptions;
|
|
71
|
+
module.exports = SchemaDateOptions;
|
package/lib/query.js
CHANGED
|
@@ -39,6 +39,31 @@ const utils = require('./utils');
|
|
|
39
39
|
const validOps = require('./helpers/query/validOps');
|
|
40
40
|
const wrapThunk = require('./helpers/query/wrapThunk');
|
|
41
41
|
|
|
42
|
+
const queryOptionMethods = new Set([
|
|
43
|
+
'allowDiskUse',
|
|
44
|
+
'batchSize',
|
|
45
|
+
'collation',
|
|
46
|
+
'comment',
|
|
47
|
+
'explain',
|
|
48
|
+
'hint',
|
|
49
|
+
'j',
|
|
50
|
+
'lean',
|
|
51
|
+
'limit',
|
|
52
|
+
'maxScan',
|
|
53
|
+
'maxTimeMS',
|
|
54
|
+
'maxscan',
|
|
55
|
+
'projection',
|
|
56
|
+
'read',
|
|
57
|
+
'select',
|
|
58
|
+
'skip',
|
|
59
|
+
'slice',
|
|
60
|
+
'sort',
|
|
61
|
+
'tailable',
|
|
62
|
+
'w',
|
|
63
|
+
'writeConcern',
|
|
64
|
+
'wtimeout'
|
|
65
|
+
]);
|
|
66
|
+
|
|
42
67
|
/**
|
|
43
68
|
* Query constructor used for building queries. You do not need
|
|
44
69
|
* to instantiate a `Query` directly. Instead use Model functions like
|
|
@@ -1630,7 +1655,19 @@ Query.prototype.setOptions = function(options, overwrite) {
|
|
|
1630
1655
|
}
|
|
1631
1656
|
}
|
|
1632
1657
|
|
|
1633
|
-
|
|
1658
|
+
// set arbitrary options
|
|
1659
|
+
for (const key of Object.keys(options)) {
|
|
1660
|
+
if (queryOptionMethods.has(key)) {
|
|
1661
|
+
const args = Array.isArray(options[key]) ?
|
|
1662
|
+
options[key] :
|
|
1663
|
+
[options[key]];
|
|
1664
|
+
this[key].apply(this, args);
|
|
1665
|
+
} else {
|
|
1666
|
+
this.options[key] = options[key];
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
return this;
|
|
1634
1671
|
};
|
|
1635
1672
|
|
|
1636
1673
|
/**
|
|
@@ -3168,23 +3205,14 @@ Query.prototype._deleteMany = wrapThunk(function(callback) {
|
|
|
3168
3205
|
*/
|
|
3169
3206
|
|
|
3170
3207
|
function completeOne(model, doc, res, options, fields, userProvidedFields, pop, callback) {
|
|
3171
|
-
const opts = pop ?
|
|
3172
|
-
{ populated: pop }
|
|
3173
|
-
: undefined;
|
|
3174
|
-
|
|
3175
3208
|
if (options.rawResult && doc == null) {
|
|
3176
3209
|
_init(null);
|
|
3177
3210
|
return null;
|
|
3178
3211
|
}
|
|
3179
3212
|
|
|
3180
|
-
|
|
3181
|
-
try {
|
|
3182
|
-
casted.$init(doc, opts, _init);
|
|
3183
|
-
} catch (error) {
|
|
3184
|
-
_init(error);
|
|
3185
|
-
}
|
|
3213
|
+
helpers.createModelAndInit(model, doc, fields, userProvidedFields, options, pop, _init);
|
|
3186
3214
|
|
|
3187
|
-
function _init(err) {
|
|
3215
|
+
function _init(err, casted) {
|
|
3188
3216
|
if (err) {
|
|
3189
3217
|
return immediate(() => callback(err));
|
|
3190
3218
|
}
|
|
@@ -5705,4 +5733,4 @@ Query.prototype.model;
|
|
|
5705
5733
|
* Export
|
|
5706
5734
|
*/
|
|
5707
5735
|
|
|
5708
|
-
module.exports = Query;
|
|
5736
|
+
module.exports = Query;
|
package/lib/queryhelpers.js
CHANGED
|
@@ -123,6 +123,23 @@ exports.createModel = function createModel(model, doc, fields, userProvidedField
|
|
|
123
123
|
return new model(undefined, fields, _opts);
|
|
124
124
|
};
|
|
125
125
|
|
|
126
|
+
/*!
|
|
127
|
+
* ignore
|
|
128
|
+
*/
|
|
129
|
+
|
|
130
|
+
exports.createModelAndInit = function createModelAndInit(model, doc, fields, userProvidedFields, options, populatedIds, callback) {
|
|
131
|
+
const initOpts = populatedIds ?
|
|
132
|
+
{ populated: populatedIds } :
|
|
133
|
+
undefined;
|
|
134
|
+
|
|
135
|
+
const casted = exports.createModel(model, doc, fields, userProvidedFields, options);
|
|
136
|
+
try {
|
|
137
|
+
casted.$init(doc, initOpts, callback);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
callback(error, casted);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
126
143
|
/*!
|
|
127
144
|
* ignore
|
|
128
145
|
*/
|
|
@@ -26,7 +26,7 @@ module.exports = SubdocumentPath;
|
|
|
26
26
|
* Single nested subdocument SchemaType constructor.
|
|
27
27
|
*
|
|
28
28
|
* @param {Schema} schema
|
|
29
|
-
* @param {String}
|
|
29
|
+
* @param {String} path
|
|
30
30
|
* @param {Object} options
|
|
31
31
|
* @inherits SchemaType
|
|
32
32
|
* @api public
|
|
@@ -243,6 +243,9 @@ SubdocumentPath.prototype.doValidate = function(value, fn, scope, options) {
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
if (options && options.skipSchemaValidators) {
|
|
246
|
+
if (!value) {
|
|
247
|
+
return fn(null);
|
|
248
|
+
}
|
|
246
249
|
return value.validate(fn);
|
|
247
250
|
}
|
|
248
251
|
|