mongoose 6.8.0 → 6.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/browser.umd.js +1 -1
- package/lib/connection.js +12 -12
- package/lib/document.js +1 -1
- package/lib/helpers/common.js +1 -0
- package/lib/helpers/model/discriminator.js +3 -0
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +4 -1
- package/lib/helpers/populate/assignVals.js +2 -0
- package/lib/helpers/query/castUpdate.js +12 -0
- package/lib/helpers/schema/applyBuiltinPlugins.js +12 -0
- package/lib/helpers/update/castArrayFilters.js +41 -15
- package/lib/index.js +32 -40
- package/lib/model.js +18 -4
- package/lib/plugins/index.js +7 -0
- package/lib/query.js +22 -6
- package/lib/schema.js +3 -0
- package/lib/types/map.js +1 -1
- package/package.json +4 -6
- package/scripts/tsc-diagnostics-check.js +15 -0
- package/tools/auth.js +2 -2
- package/tools/sharded.js +4 -4
- package/types/aggregate.d.ts +6 -6
- package/types/document.d.ts +3 -0
- package/types/index.d.ts +10 -0
- package/types/inferschematype.d.ts +11 -7
- package/types/middlewares.d.ts +1 -0
- package/types/schemaoptions.d.ts +6 -0
- package/types/schematypes.d.ts +42 -0
- package/lib/plugins/clearValidating.js +0 -28
package/lib/connection.js
CHANGED
|
@@ -196,7 +196,7 @@ Connection.prototype.collections;
|
|
|
196
196
|
*
|
|
197
197
|
* #### Example:
|
|
198
198
|
*
|
|
199
|
-
* mongoose.createConnection('mongodb://
|
|
199
|
+
* mongoose.createConnection('mongodb://127.0.0.1:27017/mydb').name; // "mydb"
|
|
200
200
|
*
|
|
201
201
|
* @property name
|
|
202
202
|
* @memberOf Connection
|
|
@@ -253,7 +253,7 @@ Connection.prototype.id;
|
|
|
253
253
|
*
|
|
254
254
|
* #### Example:
|
|
255
255
|
*
|
|
256
|
-
* const db = mongoose.createConnection('mongodb://
|
|
256
|
+
* const db = mongoose.createConnection('mongodb://127.0.0.1:27017/mydb');
|
|
257
257
|
* db.plugin(() => console.log('Applied'));
|
|
258
258
|
* db.plugins.length; // 1
|
|
259
259
|
*
|
|
@@ -277,7 +277,7 @@ Object.defineProperty(Connection.prototype, 'plugins', {
|
|
|
277
277
|
*
|
|
278
278
|
* #### Example:
|
|
279
279
|
*
|
|
280
|
-
* mongoose.createConnection('mongodb://
|
|
280
|
+
* mongoose.createConnection('mongodb://127.0.0.1:27017/mydb').host; // "127.0.0.1"
|
|
281
281
|
*
|
|
282
282
|
* @property host
|
|
283
283
|
* @memberOf Connection
|
|
@@ -297,7 +297,7 @@ Object.defineProperty(Connection.prototype, 'host', {
|
|
|
297
297
|
*
|
|
298
298
|
* #### Example:
|
|
299
299
|
*
|
|
300
|
-
* mongoose.createConnection('mongodb://
|
|
300
|
+
* mongoose.createConnection('mongodb://127.0.0.1:27017/mydb').port; // 27017
|
|
301
301
|
*
|
|
302
302
|
* @property port
|
|
303
303
|
* @memberOf Connection
|
|
@@ -316,7 +316,7 @@ Object.defineProperty(Connection.prototype, 'port', {
|
|
|
316
316
|
*
|
|
317
317
|
* #### Example:
|
|
318
318
|
*
|
|
319
|
-
* mongoose.createConnection('mongodb://val:psw@
|
|
319
|
+
* mongoose.createConnection('mongodb://val:psw@127.0.0.1:27017/mydb').user; // "val"
|
|
320
320
|
*
|
|
321
321
|
* @property user
|
|
322
322
|
* @memberOf Connection
|
|
@@ -335,7 +335,7 @@ Object.defineProperty(Connection.prototype, 'user', {
|
|
|
335
335
|
*
|
|
336
336
|
* #### Example:
|
|
337
337
|
*
|
|
338
|
-
* mongoose.createConnection('mongodb://val:psw@
|
|
338
|
+
* mongoose.createConnection('mongodb://val:psw@127.0.0.1:27017/mydb').pass; // "psw"
|
|
339
339
|
*
|
|
340
340
|
* @property pass
|
|
341
341
|
* @memberOf Connection
|
|
@@ -539,7 +539,7 @@ Connection.prototype.dropCollection = _wrapConnHelper(function dropCollection(co
|
|
|
539
539
|
*
|
|
540
540
|
* #### Example:
|
|
541
541
|
*
|
|
542
|
-
* const conn = mongoose.createConnection('mongodb://
|
|
542
|
+
* const conn = mongoose.createConnection('mongodb://127.0.0.1:27017/mydb');
|
|
543
543
|
* // Deletes the entire 'mydb' database
|
|
544
544
|
* await conn.dropDatabase();
|
|
545
545
|
*
|
|
@@ -1109,7 +1109,7 @@ Connection.prototype.collection = function(name, options) {
|
|
|
1109
1109
|
*
|
|
1110
1110
|
* #### Example:
|
|
1111
1111
|
*
|
|
1112
|
-
* const db = mongoose.createConnection('mongodb://
|
|
1112
|
+
* const db = mongoose.createConnection('mongodb://127.0.0.1:27017/mydb');
|
|
1113
1113
|
* db.plugin(() => console.log('Applied'));
|
|
1114
1114
|
* db.plugins.length; // 1
|
|
1115
1115
|
*
|
|
@@ -1367,7 +1367,7 @@ Connection.prototype.watch = function(pipeline, options) {
|
|
|
1367
1367
|
*
|
|
1368
1368
|
* #### Example:
|
|
1369
1369
|
*
|
|
1370
|
-
* const conn = await mongoose.createConnection('mongodb://
|
|
1370
|
+
* const conn = await mongoose.createConnection('mongodb://127.0.0.1:27017/test').
|
|
1371
1371
|
* asPromise();
|
|
1372
1372
|
* conn.readyState; // 1, means Mongoose is connected
|
|
1373
1373
|
*
|
|
@@ -1440,7 +1440,7 @@ Connection.prototype.optionsProvideAuthenticationData = function(options) {
|
|
|
1440
1440
|
*
|
|
1441
1441
|
* #### Example:
|
|
1442
1442
|
*
|
|
1443
|
-
* const conn = await mongoose.createConnection('mongodb://
|
|
1443
|
+
* const conn = await mongoose.createConnection('mongodb://127.0.0.1:27017/test').
|
|
1444
1444
|
* asPromise();
|
|
1445
1445
|
*
|
|
1446
1446
|
* conn.getClient(); // MongoClient { ... }
|
|
@@ -1460,7 +1460,7 @@ Connection.prototype.getClient = function getClient() {
|
|
|
1460
1460
|
*
|
|
1461
1461
|
* #### Example:
|
|
1462
1462
|
*
|
|
1463
|
-
* const client = await mongodb.MongoClient.connect('mongodb://
|
|
1463
|
+
* const client = await mongodb.MongoClient.connect('mongodb://127.0.0.1:27017/test');
|
|
1464
1464
|
*
|
|
1465
1465
|
* const conn = mongoose.createConnection().setClient(client);
|
|
1466
1466
|
*
|
|
@@ -1538,7 +1538,7 @@ Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
|
|
|
1538
1538
|
* #### Example:
|
|
1539
1539
|
*
|
|
1540
1540
|
* // Connect to `initialdb` first
|
|
1541
|
-
* const conn = await mongoose.createConnection('mongodb://
|
|
1541
|
+
* const conn = await mongoose.createConnection('mongodb://127.0.0.1:27017/initialdb').asPromise();
|
|
1542
1542
|
*
|
|
1543
1543
|
* // Creates an un-cached connection to `mydb`
|
|
1544
1544
|
* const db = conn.useDb('mydb');
|
package/lib/document.js
CHANGED
|
@@ -4655,7 +4655,7 @@ Document.prototype.getChanges = function() {
|
|
|
4655
4655
|
* Returns a copy of this document with a deep clone of `_doc` and `$__`.
|
|
4656
4656
|
*
|
|
4657
4657
|
* @return {Document} a copy of this document
|
|
4658
|
-
* @api
|
|
4658
|
+
* @api public
|
|
4659
4659
|
* @method $clone
|
|
4660
4660
|
* @memberOf Document
|
|
4661
4661
|
* @instance
|
package/lib/helpers/common.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Mixed = require('../../schema/mixed');
|
|
4
|
+
const applyBuiltinPlugins = require('../schema/applyBuiltinPlugins');
|
|
4
5
|
const defineKey = require('../document/compile').defineKey;
|
|
5
6
|
const get = require('../get');
|
|
6
7
|
const utils = require('../../utils');
|
|
@@ -40,6 +41,8 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
|
|
40
41
|
model.base._applyPlugins(schema, {
|
|
41
42
|
skipTopLevel: !applyPluginsToDiscriminators
|
|
42
43
|
});
|
|
44
|
+
} else if (!mergeHooks) {
|
|
45
|
+
applyBuiltinPlugins(schema);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
const key = model.schema.options.discriminatorKey;
|
|
@@ -43,6 +43,8 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
|
|
|
43
43
|
|
|
44
44
|
let i = 0;
|
|
45
45
|
const len = rawIds.length;
|
|
46
|
+
const hasResultArrays = Object.values(resultOrder).find(o => Array.isArray(o));
|
|
47
|
+
|
|
46
48
|
for (i = 0; i < len; ++i) {
|
|
47
49
|
id = rawIds[i];
|
|
48
50
|
|
|
@@ -77,7 +79,8 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
|
|
|
77
79
|
if (doc) {
|
|
78
80
|
if (sorting) {
|
|
79
81
|
const _resultOrder = resultOrder[sid];
|
|
80
|
-
if (
|
|
82
|
+
if (hasResultArrays) {
|
|
83
|
+
// If result arrays, rely on the MongoDB server response for ordering
|
|
81
84
|
newOrder.push(doc);
|
|
82
85
|
} else {
|
|
83
86
|
newOrder[_resultOrder] = doc;
|
|
@@ -253,6 +253,8 @@ function valueFilter(val, assignmentOpts, populateOptions, allIds) {
|
|
|
253
253
|
const _allIds = Array.isArray(allIds) ? allIds[i] : allIds;
|
|
254
254
|
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null) && !userSpecifiedTransform) {
|
|
255
255
|
continue;
|
|
256
|
+
} else if (!populateOptions.retainNullValues && subdoc == null) {
|
|
257
|
+
continue;
|
|
256
258
|
} else if (userSpecifiedTransform) {
|
|
257
259
|
subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, _allIds);
|
|
258
260
|
}
|
|
@@ -84,6 +84,14 @@ module.exports = function castUpdate(schema, obj, options, context, filter) {
|
|
|
84
84
|
const op = ops[i];
|
|
85
85
|
val = ret[op];
|
|
86
86
|
hasDollarKey = hasDollarKey || op.startsWith('$');
|
|
87
|
+
const toUnset = {};
|
|
88
|
+
if (val != null) {
|
|
89
|
+
for (const key of Object.keys(val)) {
|
|
90
|
+
if (val[key] === undefined) {
|
|
91
|
+
toUnset[key] = 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
87
95
|
|
|
88
96
|
if (val &&
|
|
89
97
|
typeof val === 'object' &&
|
|
@@ -100,6 +108,10 @@ module.exports = function castUpdate(schema, obj, options, context, filter) {
|
|
|
100
108
|
|
|
101
109
|
if (op.startsWith('$') && utils.isEmptyObject(val)) {
|
|
102
110
|
delete ret[op];
|
|
111
|
+
if (op === '$set' && !utils.isEmptyObject(toUnset)) {
|
|
112
|
+
// Unset all undefined values
|
|
113
|
+
ret['$unset'] = toUnset;
|
|
114
|
+
}
|
|
103
115
|
}
|
|
104
116
|
}
|
|
105
117
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const builtinPlugins = require('../../plugins');
|
|
4
|
+
|
|
5
|
+
module.exports = function applyBuiltinPlugins(schema) {
|
|
6
|
+
for (const plugin of Object.values(builtinPlugins)) {
|
|
7
|
+
plugin(schema, { deduplicate: true });
|
|
8
|
+
}
|
|
9
|
+
schema.plugins = Object.values(builtinPlugins).
|
|
10
|
+
map(fn => ({ fn, opts: { deduplicate: true } })).
|
|
11
|
+
concat(schema.plugins);
|
|
12
|
+
};
|
|
@@ -37,14 +37,36 @@ function _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilt
|
|
|
37
37
|
if (filter == null) {
|
|
38
38
|
throw new Error(`Got null array filter in ${arrayFilters}`);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const keys = Object.keys(filter).filter(key => filter[key] != null);
|
|
41
|
+
if (keys.length === 0) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const firstKey = keys[0];
|
|
46
|
+
if (firstKey === '$and' || firstKey === '$or') {
|
|
47
|
+
for (const key of keys) {
|
|
42
48
|
_castArrayFilters(filter[key], schema, strictQuery, updatedPathsByFilter, query);
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
if (filter[key] == null) {
|
|
46
|
-
continue;
|
|
47
49
|
}
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const dot = firstKey.indexOf('.');
|
|
53
|
+
const filterWildcardPath = dot === -1 ? firstKey : firstKey.substring(0, dot);
|
|
54
|
+
if (updatedPathsByFilter[filterWildcardPath] == null) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const baseFilterPath = cleanPositionalOperators(
|
|
58
|
+
updatedPathsByFilter[filterWildcardPath]
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const baseSchematype = getPath(schema, baseFilterPath);
|
|
62
|
+
let filterBaseSchema = baseSchematype != null ? baseSchematype.schema : null;
|
|
63
|
+
if (filterBaseSchema != null &&
|
|
64
|
+
filterBaseSchema.discriminators != null &&
|
|
65
|
+
filter[filterWildcardPath + '.' + filterBaseSchema.options.discriminatorKey]) {
|
|
66
|
+
filterBaseSchema = filterBaseSchema.discriminators[filter[filterWildcardPath + '.' + filterBaseSchema.options.discriminatorKey]] || filterBaseSchema;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const key of keys) {
|
|
48
70
|
if (updatedPathsByFilter[key] === null) {
|
|
49
71
|
continue;
|
|
50
72
|
}
|
|
@@ -52,21 +74,25 @@ function _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilt
|
|
|
52
74
|
continue;
|
|
53
75
|
}
|
|
54
76
|
const dot = key.indexOf('.');
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
77
|
+
|
|
78
|
+
let filterPathRelativeToBase = dot === -1 ? null : key.substring(dot);
|
|
79
|
+
let schematype;
|
|
80
|
+
if (filterPathRelativeToBase == null || filterBaseSchema == null) {
|
|
81
|
+
schematype = baseSchematype;
|
|
82
|
+
} else {
|
|
83
|
+
// If there are multiple array filters in the path being updated, make sure
|
|
84
|
+
// to replace them so we can get the schema path.
|
|
85
|
+
filterPathRelativeToBase = cleanPositionalOperators(filterPathRelativeToBase);
|
|
86
|
+
schematype = getPath(filterBaseSchema, filterPathRelativeToBase);
|
|
60
87
|
}
|
|
61
88
|
|
|
62
|
-
// If there are multiple array filters in the path being updated, make sure
|
|
63
|
-
// to replace them so we can get the schema path.
|
|
64
|
-
filterPath = cleanPositionalOperators(filterPath);
|
|
65
|
-
const schematype = getPath(schema, filterPath);
|
|
66
89
|
if (schematype == null) {
|
|
67
90
|
if (!strictQuery) {
|
|
68
91
|
return;
|
|
69
92
|
}
|
|
93
|
+
const filterPath = filterPathRelativeToBase == null ?
|
|
94
|
+
baseFilterPath + '.0' :
|
|
95
|
+
baseFilterPath + '.0' + filterPathRelativeToBase;
|
|
70
96
|
// For now, treat `strictQuery = true` and `strictQuery = 'throw'` as
|
|
71
97
|
// equivalent for casting array filters. `strictQuery = true` doesn't
|
|
72
98
|
// quite work in this context because we never want to silently strip out
|
package/lib/index.js
CHANGED
|
@@ -19,21 +19,17 @@ const Types = require('./types');
|
|
|
19
19
|
const Query = require('./query');
|
|
20
20
|
const Model = require('./model');
|
|
21
21
|
const applyPlugins = require('./helpers/schema/applyPlugins');
|
|
22
|
+
const builtinPlugins = require('./plugins');
|
|
22
23
|
const driver = require('./driver');
|
|
23
24
|
const promiseOrCallback = require('./helpers/promiseOrCallback');
|
|
24
25
|
const legacyPluralize = require('./helpers/pluralize');
|
|
25
26
|
const utils = require('./utils');
|
|
26
27
|
const pkg = require('../package.json');
|
|
27
28
|
const cast = require('./cast');
|
|
28
|
-
const removeSubdocs = require('./plugins/removeSubdocs');
|
|
29
|
-
const saveSubdocs = require('./plugins/saveSubdocs');
|
|
30
|
-
const trackTransaction = require('./plugins/trackTransaction');
|
|
31
|
-
const validateBeforeSave = require('./plugins/validateBeforeSave');
|
|
32
29
|
|
|
33
30
|
const Aggregate = require('./aggregate');
|
|
34
31
|
const PromiseProvider = require('./promise_provider');
|
|
35
32
|
const printStrictQueryWarning = require('./helpers/printStrictQueryWarning');
|
|
36
|
-
const shardingPlugin = require('./plugins/sharding');
|
|
37
33
|
const trusted = require('./helpers/query/trusted').trusted;
|
|
38
34
|
const sanitizeFilter = require('./helpers/query/sanitizeFilter');
|
|
39
35
|
const isBsonType = require('./helpers/isBsonType');
|
|
@@ -108,13 +104,7 @@ function Mongoose(options) {
|
|
|
108
104
|
configurable: false,
|
|
109
105
|
enumerable: true,
|
|
110
106
|
writable: false,
|
|
111
|
-
value: [
|
|
112
|
-
[saveSubdocs, { deduplicate: true }],
|
|
113
|
-
[validateBeforeSave, { deduplicate: true }],
|
|
114
|
-
[shardingPlugin, { deduplicate: true }],
|
|
115
|
-
[removeSubdocs, { deduplicate: true }],
|
|
116
|
-
[trackTransaction, { deduplicate: true }]
|
|
117
|
-
]
|
|
107
|
+
value: Object.values(builtinPlugins).map(plugin => ([plugin, { deduplicate: true }]))
|
|
118
108
|
});
|
|
119
109
|
}
|
|
120
110
|
|
|
@@ -198,26 +188,28 @@ Mongoose.prototype.setDriver = function setDriver(driver) {
|
|
|
198
188
|
* mongoose.set({ debug: true, autoIndex: false }); // set multiple options at once
|
|
199
189
|
*
|
|
200
190
|
* Currently supported options are:
|
|
201
|
-
* -
|
|
202
|
-
* -
|
|
203
|
-
* -
|
|
204
|
-
* -
|
|
205
|
-
* -
|
|
206
|
-
* -
|
|
207
|
-
* -
|
|
208
|
-
* -
|
|
209
|
-
* -
|
|
210
|
-
* -
|
|
211
|
-
* -
|
|
212
|
-
* -
|
|
213
|
-
* -
|
|
214
|
-
* -
|
|
215
|
-
* -
|
|
216
|
-
* -
|
|
217
|
-
* -
|
|
218
|
-
* -
|
|
219
|
-
* -
|
|
220
|
-
* - '
|
|
191
|
+
* - `allowDiskUse`: Set to `true` to set `allowDiskUse` to true to all aggregation operations by default.
|
|
192
|
+
* - `applyPluginsToChildSchemas`: `true` by default. Set to false to skip applying global plugins to child schemas
|
|
193
|
+
* - `applyPluginsToDiscriminators`: `false` by default. Set to true to apply global plugins to discriminator schemas. This typically isn't necessary because plugins are applied to the base schema and discriminators copy all middleware, methods, statics, and properties from the base schema.
|
|
194
|
+
* - `autoCreate`: Set to `true` to make Mongoose call [`Model.createCollection()`](/docs/api/model.html#model_Model-createCollection) automatically when you create a model with `mongoose.model()` or `conn.model()`. This is useful for testing transactions, change streams, and other features that require the collection to exist.
|
|
195
|
+
* - `autoIndex`: `true` by default. Set to false to disable automatic index creation for all models associated with this Mongoose instance.
|
|
196
|
+
* - `bufferCommands`: enable/disable mongoose's buffering mechanism for all connections and models
|
|
197
|
+
* - `bufferTimeoutMS`: If bufferCommands is on, this option sets the maximum amount of time Mongoose buffering will wait before throwing an error. If not specified, Mongoose will use 10000 (10 seconds).
|
|
198
|
+
* - `cloneSchemas`: `false` by default. Set to `true` to `clone()` all schemas before compiling into a model.
|
|
199
|
+
* - `debug`: If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arguments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
|
|
200
|
+
* - `id`: If `true`, adds a `id` virtual to all schemas unless overwritten on a per-schema basis.
|
|
201
|
+
* - `timestamps.createdAt.immutable`: `true` by default. If `false`, it will change the `createdAt` field to be [`immutable: false`](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-immutable) which means you can update the `createdAt`
|
|
202
|
+
* - `maxTimeMS`: If set, attaches [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) to every query
|
|
203
|
+
* - `objectIdGetter`: `true` by default. Mongoose adds a getter to MongoDB ObjectId's called `_id` that returns `this` for convenience with populate. Set this to false to remove the getter.
|
|
204
|
+
* - `overwriteModels`: Set to `true` to default to overwriting models with the same name when calling `mongoose.model()`, as opposed to throwing an `OverwriteModelError`.
|
|
205
|
+
* - `returnOriginal`: If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`, `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to setting the `new` option to `true` for `findOneAndX()` calls by default. Read our [`findOneAndUpdate()` tutorial](/docs/tutorials/findoneandupdate.html) for more information.
|
|
206
|
+
* - `runValidators`: `false` by default. Set to true to enable [update validators](/docs/validation.html#update-validators) for all validators by default.
|
|
207
|
+
* - `sanitizeFilter`: `false` by default. Set to true to enable the [sanitization of the query filters](/docs/api/mongoose.html#mongoose_Mongoose-sanitizeFilter) against query selector injection attacks by wrapping any nested objects that have a property whose name starts with `$` in a `$eq`.
|
|
208
|
+
* - `selectPopulatedPaths`: `true` by default. Set to false to opt out of Mongoose adding all fields that you `populate()` to your `select()`. The schema-level option `selectPopulatedPaths` overwrites this one.
|
|
209
|
+
* - `strict`: `true` by default, may be `false`, `true`, or `'throw'`. Sets the default strict mode for schemas.
|
|
210
|
+
* - `strictQuery`: same value as 'strict' by default (`true`), may be `false`, `true`, or `'throw'`. Sets the default [strictQuery](/docs/guide.html#strictQuery) mode for schemas. The default value will be switched back to `false` in Mongoose 7, use `mongoose.set('strictQuery', false);` if you want to prepare for the change.
|
|
211
|
+
* - `toJSON`: `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toJSON()`](/docs/api/document.html#document_Document-toJSON), for determining how Mongoose documents get serialized by `JSON.stringify()`
|
|
212
|
+
* - `toObject`: `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toObject()`](/docs/api/document.html#document_Document-toObject)
|
|
221
213
|
*
|
|
222
214
|
* @param {String|Object} key The name of the option or a object of multiple key-value pairs
|
|
223
215
|
* @param {String|Function|Boolean} value The value of the option, unused if "key" is a object
|
|
@@ -309,22 +301,22 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
|
|
309
301
|
* #### Example:
|
|
310
302
|
*
|
|
311
303
|
* // with mongodb:// URI
|
|
312
|
-
* db = mongoose.createConnection('mongodb://user:pass@
|
|
304
|
+
* db = mongoose.createConnection('mongodb://user:pass@127.0.0.1:port/database');
|
|
313
305
|
*
|
|
314
306
|
* // and options
|
|
315
307
|
* const opts = { db: { native_parser: true }}
|
|
316
|
-
* db = mongoose.createConnection('mongodb://user:pass@
|
|
308
|
+
* db = mongoose.createConnection('mongodb://user:pass@127.0.0.1:port/database', opts);
|
|
317
309
|
*
|
|
318
310
|
* // replica sets
|
|
319
|
-
* db = mongoose.createConnection('mongodb://user:pass@
|
|
311
|
+
* db = mongoose.createConnection('mongodb://user:pass@127.0.0.1:port,anotherhost:port,yetanother:port/database');
|
|
320
312
|
*
|
|
321
313
|
* // and options
|
|
322
314
|
* const opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
|
|
323
|
-
* db = mongoose.createConnection('mongodb://user:pass@
|
|
315
|
+
* db = mongoose.createConnection('mongodb://user:pass@127.0.0.1:port,anotherhost:port,yetanother:port/database', opts);
|
|
324
316
|
*
|
|
325
317
|
* // initialize now, connect later
|
|
326
318
|
* db = mongoose.createConnection();
|
|
327
|
-
* db.openUri('
|
|
319
|
+
* db.openUri('127.0.0.1', 'database', port, [opts]);
|
|
328
320
|
*
|
|
329
321
|
* @param {String} uri mongodb URI to connect to
|
|
330
322
|
* @param {Object} [options] passed down to the [MongoDB driver's `connect()` function](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/MongoClientOptions.html), except for 4 mongoose-specific options explained below.
|
|
@@ -367,10 +359,10 @@ Mongoose.prototype.createConnection = function(uri, options, callback) {
|
|
|
367
359
|
*
|
|
368
360
|
* #### Example:
|
|
369
361
|
*
|
|
370
|
-
* mongoose.connect('mongodb://user:pass@
|
|
362
|
+
* mongoose.connect('mongodb://user:pass@127.0.0.1:port/database');
|
|
371
363
|
*
|
|
372
364
|
* // replica sets
|
|
373
|
-
* const uri = 'mongodb://user:pass@
|
|
365
|
+
* const uri = 'mongodb://user:pass@127.0.0.1:port,anotherhost:port,yetanother:port/mydatabase';
|
|
374
366
|
* mongoose.connect(uri);
|
|
375
367
|
*
|
|
376
368
|
* // with options
|
|
@@ -786,7 +778,7 @@ Mongoose.prototype.__defineSetter__('connection', function(v) {
|
|
|
786
778
|
* mongoose.connections.length; // 1, just the default connection
|
|
787
779
|
* mongoose.connections[0] === mongoose.connection; // true
|
|
788
780
|
*
|
|
789
|
-
* mongoose.createConnection('mongodb://
|
|
781
|
+
* mongoose.createConnection('mongodb://127.0.0.1:27017/test');
|
|
790
782
|
* mongoose.connections.length; // 2
|
|
791
783
|
*
|
|
792
784
|
* @memberOf Mongoose
|
package/lib/model.js
CHANGED
|
@@ -36,6 +36,7 @@ const assignVals = require('./helpers/populate/assignVals');
|
|
|
36
36
|
const castBulkWrite = require('./helpers/model/castBulkWrite');
|
|
37
37
|
const createPopulateQueryFilter = require('./helpers/populate/createPopulateQueryFilter');
|
|
38
38
|
const getDefaultBulkwriteResult = require('./helpers/getDefaultBulkwriteResult');
|
|
39
|
+
const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
|
|
39
40
|
const discriminator = require('./helpers/model/discriminator');
|
|
40
41
|
const firstKey = require('./helpers/firstKey');
|
|
41
42
|
const each = require('./helpers/each');
|
|
@@ -1570,14 +1571,14 @@ Model.diffIndexes = function diffIndexes(options, callback) {
|
|
|
1570
1571
|
const schemaIndexes = getRelatedSchemaIndexes(model, schema.indexes());
|
|
1571
1572
|
|
|
1572
1573
|
const toDrop = getIndexesToDrop(schema, schemaIndexes, dbIndexes);
|
|
1573
|
-
const toCreate = getIndexesToCreate(schema, schemaIndexes, dbIndexes);
|
|
1574
|
+
const toCreate = getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop);
|
|
1574
1575
|
|
|
1575
1576
|
cb(null, { toDrop, toCreate });
|
|
1576
1577
|
});
|
|
1577
1578
|
});
|
|
1578
1579
|
};
|
|
1579
1580
|
|
|
1580
|
-
function getIndexesToCreate(schema, schemaIndexes, dbIndexes) {
|
|
1581
|
+
function getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop) {
|
|
1581
1582
|
const toCreate = [];
|
|
1582
1583
|
|
|
1583
1584
|
for (const [schemaIndexKeysObject, schemaIndexOptions] of schemaIndexes) {
|
|
@@ -1589,7 +1590,10 @@ function getIndexesToCreate(schema, schemaIndexes, dbIndexes) {
|
|
|
1589
1590
|
if (isDefaultIdIndex(index)) {
|
|
1590
1591
|
continue;
|
|
1591
1592
|
}
|
|
1592
|
-
if (
|
|
1593
|
+
if (
|
|
1594
|
+
isIndexEqual(schemaIndexKeysObject, options, index) &&
|
|
1595
|
+
!toDrop.includes(index.name)
|
|
1596
|
+
) {
|
|
1593
1597
|
found = true;
|
|
1594
1598
|
break;
|
|
1595
1599
|
}
|
|
@@ -1887,6 +1891,12 @@ function _ensureIndexes(model, options, callback) {
|
|
|
1887
1891
|
indexOptions.background = options.background;
|
|
1888
1892
|
}
|
|
1889
1893
|
|
|
1894
|
+
if ('toCreate' in options) {
|
|
1895
|
+
if (options.toCreate.length === 0) {
|
|
1896
|
+
return done();
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1890
1900
|
model.collection.createIndex(indexFields, indexOptions, utils.tick(function(err, name) {
|
|
1891
1901
|
indexSingleDone(err, indexFields, indexOptions, name);
|
|
1892
1902
|
if (err) {
|
|
@@ -4465,7 +4475,11 @@ Model.validate = function validate(obj, pathsToValidate, context, callback) {
|
|
|
4465
4475
|
}
|
|
4466
4476
|
|
|
4467
4477
|
return this.db.base._promiseOrCallback(callback, cb => {
|
|
4468
|
-
|
|
4478
|
+
let schema = this.schema;
|
|
4479
|
+
const discriminatorKey = schema.options.discriminatorKey;
|
|
4480
|
+
if (schema.discriminators != null && obj != null && obj[discriminatorKey] != null) {
|
|
4481
|
+
schema = getSchemaDiscriminatorByValue(schema, obj[discriminatorKey]) || schema;
|
|
4482
|
+
}
|
|
4469
4483
|
let paths = Object.keys(schema.paths);
|
|
4470
4484
|
|
|
4471
4485
|
if (pathsToValidate != null) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
exports.removeSubdocs = require('./removeSubdocs');
|
|
4
|
+
exports.saveSubdocs = require('./saveSubdocs');
|
|
5
|
+
exports.sharding = require('./sharding');
|
|
6
|
+
exports.trackTransaction = require('./trackTransaction');
|
|
7
|
+
exports.validateBeforeSave = require('./validateBeforeSave');
|
package/lib/query.js
CHANGED
|
@@ -370,17 +370,33 @@ Query.prototype.clone = function clone() {
|
|
|
370
370
|
*
|
|
371
371
|
* #### Example:
|
|
372
372
|
*
|
|
373
|
-
* query.slice('comments', 5);
|
|
374
|
-
* query.slice('comments', -5);
|
|
375
|
-
* query.slice('comments', [10, 5]);
|
|
376
|
-
* query.where('comments').slice(5);
|
|
377
|
-
* query.where('comments').slice([-10, 5]);
|
|
373
|
+
* query.slice('comments', 5); // Returns the first 5 comments
|
|
374
|
+
* query.slice('comments', -5); // Returns the last 5 comments
|
|
375
|
+
* query.slice('comments', [10, 5]); // Returns the first 5 comments after the 10-th
|
|
376
|
+
* query.where('comments').slice(5); // Returns the first 5 comments
|
|
377
|
+
* query.where('comments').slice([-10, 5]); // Returns the first 5 comments after the 10-th to last
|
|
378
|
+
*
|
|
379
|
+
* **Note:** If the absolute value of the number of elements to be sliced is greater than the number of elements in the array, all array elements will be returned.
|
|
380
|
+
*
|
|
381
|
+
* // Given `arr`: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
382
|
+
* query.slice('arr', 20); // Returns [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
383
|
+
* query.slice('arr', -20); // Returns [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
384
|
+
*
|
|
385
|
+
* **Note:** If the number of elements to skip is positive and greater than the number of elements in the array, an empty array will be returned.
|
|
386
|
+
*
|
|
387
|
+
* // Given `arr`: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
388
|
+
* query.slice('arr', [20, 5]); // Returns []
|
|
389
|
+
*
|
|
390
|
+
* **Note:** If the number of elements to skip is negative and its absolute value is greater than the number of elements in the array, the starting position is the start of the array.
|
|
391
|
+
*
|
|
392
|
+
* // Given `arr`: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
393
|
+
* query.slice('arr', [-20, 5]); // Returns [1, 2, 3, 4, 5]
|
|
378
394
|
*
|
|
379
395
|
* @method slice
|
|
380
396
|
* @memberOf Query
|
|
381
397
|
* @instance
|
|
382
398
|
* @param {String} [path]
|
|
383
|
-
* @param {Number} val number
|
|
399
|
+
* @param {Number|Array} val number of elements to slice or array with number of elements to skip and number of elements to slice
|
|
384
400
|
* @return {Query} this
|
|
385
401
|
* @see mongodb https://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements
|
|
386
402
|
* @see $slice https://docs.mongodb.org/manual/reference/projection/slice/#prj._S_slice
|
package/lib/schema.js
CHANGED
|
@@ -1250,6 +1250,9 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
|
|
1250
1250
|
if (options.hasOwnProperty('strict')) {
|
|
1251
1251
|
childSchemaOptions.strict = options.strict;
|
|
1252
1252
|
}
|
|
1253
|
+
if (options.hasOwnProperty('strictQuery')) {
|
|
1254
|
+
childSchemaOptions.strictQuery = options.strictQuery;
|
|
1255
|
+
}
|
|
1253
1256
|
|
|
1254
1257
|
if (this._userProvidedOptions.hasOwnProperty('_id')) {
|
|
1255
1258
|
childSchemaOptions._id = this._userProvidedOptions._id;
|
package/lib/types/map.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mongoose",
|
|
3
3
|
"description": "Mongoose MongoDB ODM",
|
|
4
|
-
"version": "6.8.
|
|
4
|
+
"version": "6.8.2",
|
|
5
5
|
"author": "Guillermo Rauch <guillermo@learnboost.com>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mongodb",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"acquit-ignore": "0.2.0",
|
|
37
37
|
"acquit-require": "0.1.1",
|
|
38
38
|
"assert-browserify": "2.0.0",
|
|
39
|
-
"axios": "1.
|
|
39
|
+
"axios": "1.1.3",
|
|
40
40
|
"babel-loader": "8.2.5",
|
|
41
41
|
"benchmark": "2.1.4",
|
|
42
42
|
"bluebird": "3.7.2",
|
|
@@ -61,9 +61,8 @@
|
|
|
61
61
|
"q": "1.5.1",
|
|
62
62
|
"sinon": "15.0.0",
|
|
63
63
|
"stream-browserify": "3.0.0",
|
|
64
|
-
"ts-benchmark": "^1.1.10",
|
|
65
64
|
"tsd": "0.25.0",
|
|
66
|
-
"typescript": "4.
|
|
65
|
+
"typescript": "4.9.4",
|
|
67
66
|
"uuid": "9.0.0",
|
|
68
67
|
"webpack": "5.75.0"
|
|
69
68
|
},
|
|
@@ -100,8 +99,7 @@
|
|
|
100
99
|
"test-tsd": "node ./test/types/check-types-filename && tsd",
|
|
101
100
|
"tdd": "mocha ./test/*.test.js --inspect --watch --recursive --watch-files ./**/*.{js,ts}",
|
|
102
101
|
"test-coverage": "nyc --reporter=html --reporter=text npm test",
|
|
103
|
-
"ts-benchmark": "
|
|
104
|
-
"ts-benchmark-watch": "ts-benchmark -p ./benchmarks/typescript/simple -w ./types -i -s -f 17/100000 18 29 32 -b master"
|
|
102
|
+
"ts-benchmark": "cd ./benchmarks/typescript/simple && npm install && npm run benchmark | node ../../../scripts/tsc-diagnostics-check"
|
|
105
103
|
},
|
|
106
104
|
"main": "./index.js",
|
|
107
105
|
"types": "./types/index.d.ts",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
const stdin = fs.readFileSync(0).toString('utf8');
|
|
6
|
+
const maxInstantiations = isNaN(process.argv[2]) ? 100000 : parseInt(process.argv[2], 10);
|
|
7
|
+
|
|
8
|
+
console.log(stdin);
|
|
9
|
+
|
|
10
|
+
const numInstantiations = parseInt(stdin.match(/Instantiations:\s+(\d+)/)[1], 10);
|
|
11
|
+
if (numInstantiations > maxInstantiations) {
|
|
12
|
+
throw new Error(`Instantiations ${numInstantiations} > max ${maxInstantiations}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
process.exit(0);
|