mongoose 9.0.1 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/aggregate.js +1 -1
- package/lib/cast/string.js +1 -1
- package/lib/cast.js +7 -15
- package/lib/collection.js +2 -2
- package/lib/connection.js +20 -14
- package/lib/cursor/changeStream.js +5 -5
- package/lib/document.js +126 -79
- package/lib/drivers/node-mongodb-native/collection.js +33 -126
- package/lib/drivers/node-mongodb-native/connection.js +8 -23
- package/lib/error/cast.js +1 -1
- package/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +4 -4
- package/lib/helpers/clone.js +8 -8
- package/lib/helpers/common.js +4 -4
- package/lib/helpers/cursor/eachAsync.js +1 -1
- package/lib/helpers/discriminator/getConstructor.js +1 -1
- package/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +1 -1
- package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +2 -2
- package/lib/helpers/document/applyDefaults.js +1 -1
- package/lib/helpers/document/applyTimestamps.js +2 -1
- package/lib/helpers/document/applyVirtuals.js +4 -3
- package/lib/helpers/document/cleanModifiedSubpaths.js +1 -1
- package/lib/helpers/document/compile.js +4 -4
- package/lib/helpers/document/getDeepestSubdocumentForPath.js +1 -1
- package/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +1 -1
- package/lib/helpers/indexes/getRelatedIndexes.js +3 -3
- package/lib/helpers/model/castBulkWrite.js +5 -9
- package/lib/helpers/model/discriminator.js +1 -1
- package/lib/helpers/populate/assignRawDocsToIdStructure.js +1 -1
- package/lib/helpers/populate/assignVals.js +4 -4
- package/lib/helpers/populate/getModelsMapForPopulate.js +25 -23
- package/lib/helpers/populate/getSchemaTypes.js +6 -7
- package/lib/helpers/printJestWarning.js +1 -1
- package/lib/helpers/processConnectionOptions.js +1 -1
- package/lib/helpers/query/castUpdate.js +12 -12
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +2 -2
- package/lib/helpers/query/handleImmutable.js +2 -2
- package/lib/helpers/query/sanitizeFilter.js +1 -1
- package/lib/helpers/schema/applyPlugins.js +1 -1
- package/lib/helpers/schema/applyReadConcern.js +1 -1
- package/lib/helpers/schema/applyWriteConcern.js +4 -2
- package/lib/helpers/schema/getIndexes.js +3 -3
- package/lib/helpers/schema/getSubdocumentStrictValue.js +1 -1
- package/lib/helpers/schema/handleIdOption.js +1 -1
- package/lib/helpers/schema/idGetter.js +1 -1
- package/lib/helpers/schematype/handleImmutable.js +1 -1
- package/lib/helpers/setDefaultsOnInsert.js +2 -5
- package/lib/helpers/timestamps/setDocumentTimestamps.js +2 -2
- package/lib/helpers/timestamps/setupTimestamps.js +2 -2
- package/lib/helpers/update/applyTimestampsToUpdate.js +10 -9
- package/lib/helpers/update/castArrayFilters.js +4 -4
- package/lib/helpers/update/decorateUpdateWithVersionKey.js +1 -1
- package/lib/helpers/updateValidators.js +4 -4
- package/lib/model.js +42 -48
- package/lib/mongoose.js +5 -5
- package/lib/options/virtualOptions.js +1 -1
- package/lib/plugins/saveSubdocs.js +2 -2
- package/lib/plugins/trackTransaction.js +3 -4
- package/lib/query.js +62 -59
- package/lib/queryHelpers.js +9 -12
- package/lib/schema/array.js +10 -12
- package/lib/schema/buffer.js +6 -6
- package/lib/schema/documentArray.js +15 -23
- package/lib/schema/documentArrayElement.js +3 -3
- package/lib/schema/map.js +1 -1
- package/lib/schema/mixed.js +2 -2
- package/lib/schema/number.js +22 -4
- package/lib/schema/objectId.js +1 -1
- package/lib/schema/operators/exists.js +1 -1
- package/lib/schema/operators/geospatial.js +1 -1
- package/lib/schema/string.js +2 -2
- package/lib/schema/subdocument.js +9 -12
- package/lib/schema/union.js +1 -1
- package/lib/schema.js +27 -28
- package/lib/schemaType.js +11 -11
- package/lib/types/array/index.js +2 -2
- package/lib/types/array/methods/index.js +38 -8
- package/lib/types/arraySubdocument.js +12 -2
- package/lib/types/buffer.js +1 -1
- package/lib/types/documentArray/index.js +2 -2
- package/lib/types/documentArray/methods/index.js +5 -5
- package/lib/types/map.js +8 -8
- package/lib/types/subdocument.js +15 -5
- package/lib/utils.js +23 -7
- package/package.json +3 -2
- package/types/index.d.ts +26 -9
- package/types/inferrawdoctype.d.ts +9 -3
- package/types/inferschematype.d.ts +20 -27
- package/types/middlewares.d.ts +11 -0
- package/types/models.d.ts +15 -5
- package/types/query.d.ts +1 -1
- package/types/schemaoptions.d.ts +4 -2
- package/types/utility.d.ts +1 -1
- package/types/virtuals.d.ts +3 -3
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const get = require('../get');
|
|
8
|
+
const utils = require('../../utils');
|
|
8
9
|
|
|
9
10
|
module.exports = applyTimestampsToUpdate;
|
|
10
11
|
|
|
@@ -22,11 +23,11 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
22
23
|
return currentUpdate;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
const skipCreatedAt = timestamps
|
|
26
|
-
const skipUpdatedAt = timestamps
|
|
26
|
+
const skipCreatedAt = timestamps?.createdAt === false;
|
|
27
|
+
const skipUpdatedAt = timestamps?.updatedAt === false;
|
|
27
28
|
|
|
28
29
|
if (isReplace) {
|
|
29
|
-
if (currentUpdate
|
|
30
|
+
if (currentUpdate?.$set) {
|
|
30
31
|
currentUpdate = currentUpdate.$set;
|
|
31
32
|
updates.$set = {};
|
|
32
33
|
_updates = updates.$set;
|
|
@@ -51,7 +52,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
51
52
|
}
|
|
52
53
|
updates.$set = updates.$set || {};
|
|
53
54
|
if (!skipUpdatedAt && updatedAt &&
|
|
54
|
-
|
|
55
|
+
!currentUpdate.$currentDate?.[updatedAt]) {
|
|
55
56
|
let timestampSet = false;
|
|
56
57
|
if (updatedAt.indexOf('.') !== -1) {
|
|
57
58
|
const pieces = updatedAt.split('.');
|
|
@@ -62,7 +63,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
62
63
|
currentUpdate[start][remnant] = now;
|
|
63
64
|
timestampSet = true;
|
|
64
65
|
break;
|
|
65
|
-
} else if (currentUpdate.$set
|
|
66
|
+
} else if (currentUpdate.$set?.[start]) {
|
|
66
67
|
currentUpdate.$set[start][remnant] = now;
|
|
67
68
|
timestampSet = true;
|
|
68
69
|
break;
|
|
@@ -81,7 +82,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
81
82
|
|
|
82
83
|
if (!skipCreatedAt && createdAt) {
|
|
83
84
|
const overwriteImmutable = get(options, 'overwriteImmutable', false);
|
|
84
|
-
const hasUserCreatedAt = currentUpdate[createdAt] != null || currentUpdate
|
|
85
|
+
const hasUserCreatedAt = currentUpdate[createdAt] != null || currentUpdate.$set?.[createdAt] != null;
|
|
85
86
|
|
|
86
87
|
// If overwriteImmutable is true and user provided createdAt, keep their value
|
|
87
88
|
if (overwriteImmutable && hasUserCreatedAt) {
|
|
@@ -95,7 +96,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
95
96
|
if (currentUpdate[createdAt]) {
|
|
96
97
|
delete currentUpdate[createdAt];
|
|
97
98
|
}
|
|
98
|
-
if (currentUpdate.$set
|
|
99
|
+
if (currentUpdate.$set?.[createdAt]) {
|
|
99
100
|
delete currentUpdate.$set[createdAt];
|
|
100
101
|
}
|
|
101
102
|
let timestampSet = false;
|
|
@@ -108,7 +109,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
108
109
|
currentUpdate[start][remnant] = now;
|
|
109
110
|
timestampSet = true;
|
|
110
111
|
break;
|
|
111
|
-
} else if (currentUpdate.$set
|
|
112
|
+
} else if (currentUpdate.$set?.[start]) {
|
|
112
113
|
currentUpdate.$set[start][remnant] = now;
|
|
113
114
|
timestampSet = true;
|
|
114
115
|
break;
|
|
@@ -123,7 +124,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio
|
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
if (
|
|
127
|
+
if (utils.hasOwnKeys(updates.$set) === false) {
|
|
127
128
|
delete updates.$set;
|
|
128
129
|
}
|
|
129
130
|
return updates;
|
|
@@ -4,6 +4,7 @@ const castFilterPath = require('../query/castFilterPath');
|
|
|
4
4
|
const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
|
|
5
5
|
const getPath = require('../schema/getPath');
|
|
6
6
|
const updatedPathsByArrayFilter = require('./updatedPathsByArrayFilter');
|
|
7
|
+
const utils = require('../../utils');
|
|
7
8
|
|
|
8
9
|
module.exports = function castArrayFilters(query) {
|
|
9
10
|
const arrayFilters = query.options.arrayFilters;
|
|
@@ -18,7 +19,7 @@ module.exports = function castArrayFilters(query) {
|
|
|
18
19
|
if (query._mongooseOptions.strict != null) {
|
|
19
20
|
strictQuery = query._mongooseOptions.strict;
|
|
20
21
|
}
|
|
21
|
-
if (query.model
|
|
22
|
+
if (query.model?.base.options.strictQuery != null) {
|
|
22
23
|
strictQuery = query.model.base.options.strictQuery;
|
|
23
24
|
}
|
|
24
25
|
if (schema._userProvidedOptions.strictQuery != null) {
|
|
@@ -63,8 +64,7 @@ function _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilt
|
|
|
63
64
|
|
|
64
65
|
const baseSchematype = getPath(schema, baseFilterPath, discriminatorValueMap);
|
|
65
66
|
let filterBaseSchema = baseSchematype != null ? baseSchematype.schema : null;
|
|
66
|
-
if (filterBaseSchema != null &&
|
|
67
|
-
filterBaseSchema.discriminators != null &&
|
|
67
|
+
if (filterBaseSchema?.discriminators != null &&
|
|
68
68
|
filter[filterWildcardPath + '.' + filterBaseSchema.options.discriminatorKey]) {
|
|
69
69
|
filterBaseSchema = filterBaseSchema.discriminators[filter[filterWildcardPath + '.' + filterBaseSchema.options.discriminatorKey]] || filterBaseSchema;
|
|
70
70
|
discriminatorValueMap[baseFilterPath] = filter[filterWildcardPath + '.' + filterBaseSchema.options.discriminatorKey];
|
|
@@ -74,7 +74,7 @@ function _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilt
|
|
|
74
74
|
if (updatedPathsByFilter[key] === null) {
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
|
-
if (
|
|
77
|
+
if (utils.hasOwnKeys(updatedPathsByFilter) === false) {
|
|
78
78
|
continue;
|
|
79
79
|
}
|
|
80
80
|
const dot = key.indexOf('.');
|
|
@@ -38,7 +38,7 @@ module.exports = async function updateValidators(query, schema, castedDoc, optio
|
|
|
38
38
|
const _keys = Object.keys(castedDoc[keys[i]]);
|
|
39
39
|
for (let ii = 0; ii < _keys.length; ++ii) {
|
|
40
40
|
currentUpdate = castedDoc[keys[i]][_keys[ii]];
|
|
41
|
-
if (currentUpdate
|
|
41
|
+
if (currentUpdate?.$each) {
|
|
42
42
|
arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []).
|
|
43
43
|
concat(currentUpdate.$each);
|
|
44
44
|
} else {
|
|
@@ -109,7 +109,7 @@ module.exports = async function updateValidators(query, schema, castedDoc, optio
|
|
|
109
109
|
continue;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
if (schemaPath.$isMongooseDocumentArrayElement && v
|
|
112
|
+
if (schemaPath.$isMongooseDocumentArrayElement && v?.$__ != null) {
|
|
113
113
|
alreadyValidated.push(updates[i]);
|
|
114
114
|
validatorsToExecute.push(
|
|
115
115
|
schemaPath.doValidate(v, context, { updateValidator: true }).catch(err => {
|
|
@@ -158,7 +158,7 @@ module.exports = async function updateValidators(query, schema, castedDoc, optio
|
|
|
158
158
|
validatorsToExecute.push(
|
|
159
159
|
schemaPath.doValidate(
|
|
160
160
|
arrayAtomicUpdates[arrayUpdate],
|
|
161
|
-
options
|
|
161
|
+
options?.context === 'query' ? query : null
|
|
162
162
|
).catch(err => {
|
|
163
163
|
err.path = arrayUpdate;
|
|
164
164
|
validationErrors.push(err);
|
|
@@ -170,7 +170,7 @@ module.exports = async function updateValidators(query, schema, castedDoc, optio
|
|
|
170
170
|
validatorsToExecute.push(
|
|
171
171
|
schemaPath.doValidate(
|
|
172
172
|
atomicUpdate,
|
|
173
|
-
options
|
|
173
|
+
options?.context === 'query' ? query : null,
|
|
174
174
|
{ updateValidator: true }
|
|
175
175
|
).catch(err => {
|
|
176
176
|
err.path = arrayUpdate;
|
package/lib/model.js
CHANGED
|
@@ -434,7 +434,7 @@ Model.prototype.$__save = async function $__save(options) {
|
|
|
434
434
|
continue;
|
|
435
435
|
}
|
|
436
436
|
minimize(updateOp[key]);
|
|
437
|
-
if (
|
|
437
|
+
if (utils.hasOwnKeys(updateOp[key]) === false) {
|
|
438
438
|
delete updateOp[key];
|
|
439
439
|
update.$unset = update.$unset || {};
|
|
440
440
|
update.$unset[key] = 1;
|
|
@@ -754,7 +754,7 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
754
754
|
|
|
755
755
|
const self = this;
|
|
756
756
|
const where = this.$__where();
|
|
757
|
-
const query = self.constructor.deleteOne(
|
|
757
|
+
const query = self.constructor.deleteOne();
|
|
758
758
|
|
|
759
759
|
if (this.$session() != null) {
|
|
760
760
|
if (!('session' in query.options)) {
|
|
@@ -763,12 +763,13 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
763
763
|
}
|
|
764
764
|
|
|
765
765
|
query.pre(async function queryPreDeleteOne() {
|
|
766
|
-
const res = await self.constructor._middleware.execPre('deleteOne', self, [self]);
|
|
766
|
+
const res = await self.constructor._middleware.execPre('deleteOne', self, [self, options]);
|
|
767
767
|
// `self` is passed to pre hooks as argument for backwards compatibility, but that
|
|
768
768
|
// isn't the actual arguments passed to the wrapped function.
|
|
769
|
-
if (res
|
|
769
|
+
if (res[0] !== self || res[1] !== options) {
|
|
770
770
|
throw new Error('Document deleteOne pre hooks cannot overwrite arguments');
|
|
771
771
|
}
|
|
772
|
+
query.deleteOne(where, options);
|
|
772
773
|
// Apply custom where conditions _after_ document deleteOne middleware for
|
|
773
774
|
// consistency with save() - sharding plugin needs to set $where
|
|
774
775
|
if (self.$where != null) {
|
|
@@ -790,6 +791,12 @@ Model.prototype.deleteOne = function deleteOne(options) {
|
|
|
790
791
|
query.post(function queryPostDeleteOne() {
|
|
791
792
|
return self.constructor._middleware.execPost('deleteOne', self, [self], {});
|
|
792
793
|
});
|
|
794
|
+
query.transform(function setIsDeleted(result) {
|
|
795
|
+
if (result?.deletedCount > 0) {
|
|
796
|
+
self.$isDeleted(true);
|
|
797
|
+
}
|
|
798
|
+
return result;
|
|
799
|
+
});
|
|
793
800
|
|
|
794
801
|
return query;
|
|
795
802
|
};
|
|
@@ -1146,25 +1153,16 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1146
1153
|
throw err;
|
|
1147
1154
|
});
|
|
1148
1155
|
|
|
1149
|
-
const collectionOptions = this
|
|
1150
|
-
this.schema &&
|
|
1151
|
-
this.schema.options &&
|
|
1152
|
-
this.schema.options.collectionOptions;
|
|
1156
|
+
const collectionOptions = this?.schema?.options?.collectionOptions;
|
|
1153
1157
|
if (collectionOptions != null) {
|
|
1154
1158
|
options = Object.assign({}, collectionOptions, options);
|
|
1155
1159
|
}
|
|
1156
1160
|
|
|
1157
|
-
const schemaCollation = this
|
|
1158
|
-
this.schema &&
|
|
1159
|
-
this.schema.options &&
|
|
1160
|
-
this.schema.options.collation;
|
|
1161
|
+
const schemaCollation = this?.schema?.options?.collation;
|
|
1161
1162
|
if (schemaCollation != null) {
|
|
1162
1163
|
options = Object.assign({ collation: schemaCollation }, options);
|
|
1163
1164
|
}
|
|
1164
|
-
const capped = this
|
|
1165
|
-
this.schema &&
|
|
1166
|
-
this.schema.options &&
|
|
1167
|
-
this.schema.options.capped;
|
|
1165
|
+
const capped = this?.schema?.options?.capped;
|
|
1168
1166
|
if (capped != null) {
|
|
1169
1167
|
if (typeof capped === 'number') {
|
|
1170
1168
|
options = Object.assign({ capped: true, size: capped }, options);
|
|
@@ -1172,10 +1170,7 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1172
1170
|
options = Object.assign({ capped: true }, capped, options);
|
|
1173
1171
|
}
|
|
1174
1172
|
}
|
|
1175
|
-
const timeseries = this
|
|
1176
|
-
this.schema &&
|
|
1177
|
-
this.schema.options &&
|
|
1178
|
-
this.schema.options.timeseries;
|
|
1173
|
+
const timeseries = this?.schema?.options?.timeseries;
|
|
1179
1174
|
if (timeseries != null) {
|
|
1180
1175
|
options = Object.assign({ timeseries }, options);
|
|
1181
1176
|
if (options.expireAfterSeconds != null) {
|
|
@@ -1190,10 +1185,7 @@ Model.createCollection = async function createCollection(options) {
|
|
|
1190
1185
|
}
|
|
1191
1186
|
}
|
|
1192
1187
|
|
|
1193
|
-
const clusteredIndex = this
|
|
1194
|
-
this.schema &&
|
|
1195
|
-
this.schema.options &&
|
|
1196
|
-
this.schema.options.clusteredIndex;
|
|
1188
|
+
const clusteredIndex = this?.schema?.options?.clusteredIndex;
|
|
1197
1189
|
if (clusteredIndex != null) {
|
|
1198
1190
|
options = Object.assign({ clusteredIndex: { ...clusteredIndex, unique: true } }, options);
|
|
1199
1191
|
}
|
|
@@ -1495,7 +1487,7 @@ Model.cleanIndexes = async function cleanIndexes(options) {
|
|
|
1495
1487
|
}
|
|
1496
1488
|
const model = this;
|
|
1497
1489
|
|
|
1498
|
-
if (Array.isArray(options
|
|
1490
|
+
if (Array.isArray(options?.toDrop)) {
|
|
1499
1491
|
const res = await _dropIndexes(options.toDrop, model, options);
|
|
1500
1492
|
return res;
|
|
1501
1493
|
}
|
|
@@ -1510,7 +1502,7 @@ async function _dropIndexes(toDrop, model, options) {
|
|
|
1510
1502
|
}
|
|
1511
1503
|
|
|
1512
1504
|
const collection = model.$__collection;
|
|
1513
|
-
if (options
|
|
1505
|
+
if (options?.hideIndexes) {
|
|
1514
1506
|
await Promise.all(toDrop.map(indexName => {
|
|
1515
1507
|
return model.db.db.command({
|
|
1516
1508
|
collMod: collection.collectionName,
|
|
@@ -1854,7 +1846,7 @@ Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
|
1854
1846
|
let currentSchema = this.schema;
|
|
1855
1847
|
for (const i in fieldKeys) {
|
|
1856
1848
|
const name = fieldKeys[i];
|
|
1857
|
-
if (currentSchema
|
|
1849
|
+
if (currentSchema?.aliases[name]) {
|
|
1858
1850
|
alias = currentSchema.aliases[name];
|
|
1859
1851
|
if (errorOnDuplicates && alias in fields) {
|
|
1860
1852
|
throw new MongooseError(`Provided object has both field "${name}" and its alias "${alias}"`);
|
|
@@ -1868,7 +1860,7 @@ Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
|
1868
1860
|
}
|
|
1869
1861
|
|
|
1870
1862
|
// Check if aliased path is a schema
|
|
1871
|
-
if (currentSchema
|
|
1863
|
+
if (currentSchema?.paths[alias]) {
|
|
1872
1864
|
currentSchema = currentSchema.paths[alias].schema;
|
|
1873
1865
|
}
|
|
1874
1866
|
else
|
|
@@ -3054,13 +3046,13 @@ Model.insertMany = async function insertMany(arr, options) {
|
|
|
3054
3046
|
// `writeErrors` is a property reported by the MongoDB driver,
|
|
3055
3047
|
// just not if there's only 1 error.
|
|
3056
3048
|
if (error.writeErrors == null &&
|
|
3057
|
-
|
|
3049
|
+
error.result?.result?.writeErrors != null) {
|
|
3058
3050
|
error.writeErrors = error.result.result.writeErrors;
|
|
3059
3051
|
}
|
|
3060
3052
|
|
|
3061
3053
|
// `insertedDocs` is a Mongoose-specific property
|
|
3062
|
-
const hasWriteErrors = error
|
|
3063
|
-
const erroredIndexes = new Set((error
|
|
3054
|
+
const hasWriteErrors = error?.writeErrors;
|
|
3055
|
+
const erroredIndexes = new Set((error?.writeErrors || []).map(err => err.index));
|
|
3064
3056
|
|
|
3065
3057
|
if (error.writeErrors != null) {
|
|
3066
3058
|
for (let i = 0; i < error.writeErrors.length; ++i) {
|
|
@@ -3248,12 +3240,14 @@ function _setIsNew(doc, val) {
|
|
|
3248
3240
|
* @param {Object} [ops.updateOne.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
|
|
3249
3241
|
* @param {Boolean} [ops.updateOne.upsert=false] If true, insert a doc if none match
|
|
3250
3242
|
* @param {Boolean} [ops.updateOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3243
|
+
* @param {Boolean} [ops.updateOne.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.
|
|
3251
3244
|
* @param {Object} [ops.updateOne.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
|
|
3252
3245
|
* @param {Array} [ops.updateOne.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
|
|
3253
3246
|
* @param {Object} [ops.updateMany.filter] Update all the documents that match this filter
|
|
3254
3247
|
* @param {Object} [ops.updateMany.update] An object containing [update operators](https://www.mongodb.com/docs/manual/reference/operator/update/)
|
|
3255
3248
|
* @param {Boolean} [ops.updateMany.upsert=false] If true, insert a doc if no documents match `filter`
|
|
3256
3249
|
* @param {Boolean} [ops.updateMany.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
|
|
3250
|
+
* @param {Boolean} [ops.updateMany.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.
|
|
3257
3251
|
* @param {Object} [ops.updateMany.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
|
|
3258
3252
|
* @param {Array} [ops.updateMany.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
|
|
3259
3253
|
* @param {Object} [ops.deleteOne.filter] Delete the first document that matches this filter
|
|
@@ -3286,12 +3280,15 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3286
3280
|
}
|
|
3287
3281
|
options = options || {};
|
|
3288
3282
|
|
|
3289
|
-
|
|
3283
|
+
try {
|
|
3284
|
+
[ops, options] = await this.hooks.execPre('bulkWrite', this, [ops, options]);
|
|
3285
|
+
} catch (err) {
|
|
3290
3286
|
if (err instanceof Kareem.skipWrappedFunction) {
|
|
3291
|
-
|
|
3287
|
+
ops = err;
|
|
3288
|
+
} else {
|
|
3289
|
+
await this.hooks.execPost('bulkWrite', this, [null], { error: err });
|
|
3292
3290
|
}
|
|
3293
|
-
|
|
3294
|
-
});
|
|
3291
|
+
}
|
|
3295
3292
|
|
|
3296
3293
|
if (ops instanceof Kareem.skipWrappedFunction) {
|
|
3297
3294
|
return ops.args[0];
|
|
@@ -3486,7 +3483,7 @@ Model.bulkSave = async function bulkSave(documents, options) {
|
|
|
3486
3483
|
const successfulDocuments = [];
|
|
3487
3484
|
for (let i = 0; i < documents.length; i++) {
|
|
3488
3485
|
const document = documents[i];
|
|
3489
|
-
const documentError = bulkWriteError
|
|
3486
|
+
const documentError = bulkWriteError?.writeErrors.find(writeError => {
|
|
3490
3487
|
const writeErrorDocumentId = writeError.err.op._id || writeError.err.op.q._id;
|
|
3491
3488
|
return writeErrorDocumentId.toString() === document._doc._id.toString();
|
|
3492
3489
|
});
|
|
@@ -3650,7 +3647,7 @@ Model.castObject = function castObject(obj, options) {
|
|
|
3650
3647
|
|
|
3651
3648
|
for (const path of paths) {
|
|
3652
3649
|
const schemaType = schema.path(path);
|
|
3653
|
-
if (!schemaType
|
|
3650
|
+
if (!schemaType?.$isMongooseArray) {
|
|
3654
3651
|
continue;
|
|
3655
3652
|
}
|
|
3656
3653
|
|
|
@@ -3839,7 +3836,7 @@ Model.hydrate = function(obj, projection, options) {
|
|
|
3839
3836
|
}
|
|
3840
3837
|
|
|
3841
3838
|
if (projection != null) {
|
|
3842
|
-
if (obj
|
|
3839
|
+
if (obj?.$__ != null) {
|
|
3843
3840
|
obj = obj.toObject(internalToObjectOptions);
|
|
3844
3841
|
}
|
|
3845
3842
|
obj = applyProjection(obj, projection);
|
|
@@ -3978,7 +3975,7 @@ Model.updateOne = function updateOne(conditions, doc, options) {
|
|
|
3978
3975
|
Model.replaceOne = function replaceOne(conditions, doc, options) {
|
|
3979
3976
|
_checkContext(this, 'replaceOne');
|
|
3980
3977
|
|
|
3981
|
-
const versionKey = this
|
|
3978
|
+
const versionKey = this?.schema?.options?.versionKey || null;
|
|
3982
3979
|
if (versionKey && !doc[versionKey]) {
|
|
3983
3980
|
doc[versionKey] = 0;
|
|
3984
3981
|
}
|
|
@@ -4004,10 +4001,7 @@ function _update(model, op, conditions, doc, options) {
|
|
|
4004
4001
|
}
|
|
4005
4002
|
options = typeof options === 'function' ? options : clone(options);
|
|
4006
4003
|
|
|
4007
|
-
const versionKey = model
|
|
4008
|
-
model.schema &&
|
|
4009
|
-
model.schema.options &&
|
|
4010
|
-
model.schema.options.versionKey || null;
|
|
4004
|
+
const versionKey = model?.schema?.options?.versionKey || null;
|
|
4011
4005
|
decorateUpdateWithVersionKey(doc, options, versionKey);
|
|
4012
4006
|
|
|
4013
4007
|
return mq[op](conditions, doc, options);
|
|
@@ -4146,7 +4140,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4146
4140
|
|
|
4147
4141
|
for (const path of paths) {
|
|
4148
4142
|
const schemaType = schema.path(path);
|
|
4149
|
-
if (!schemaType
|
|
4143
|
+
if (!schemaType?.$isMongooseArray || schemaType.$isMongooseDocumentArray) {
|
|
4150
4144
|
continue;
|
|
4151
4145
|
}
|
|
4152
4146
|
|
|
@@ -4294,7 +4288,7 @@ const excludeIdRegGlobal = /\s?-_id\s?/g;
|
|
|
4294
4288
|
|
|
4295
4289
|
async function _populatePath(model, docs, populateOptions) {
|
|
4296
4290
|
if (populateOptions.strictPopulate == null) {
|
|
4297
|
-
if (populateOptions._localModel
|
|
4291
|
+
if (populateOptions._localModel?.schema._userProvidedOptions.strictPopulate != null) {
|
|
4298
4292
|
populateOptions.strictPopulate = populateOptions._localModel.schema._userProvidedOptions.strictPopulate;
|
|
4299
4293
|
} else if (populateOptions._localModel != null && model.base.options.strictPopulate != null) {
|
|
4300
4294
|
populateOptions.strictPopulate = model.base.options.strictPopulate;
|
|
@@ -4378,7 +4372,7 @@ async function _populatePath(model, docs, populateOptions) {
|
|
|
4378
4372
|
}
|
|
4379
4373
|
}
|
|
4380
4374
|
|
|
4381
|
-
if (mod.options.options
|
|
4375
|
+
if (mod.options.options?.limit != null) {
|
|
4382
4376
|
assignmentOpts.originalLimit = mod.options.options.limit;
|
|
4383
4377
|
} else if (mod.options.limit != null) {
|
|
4384
4378
|
assignmentOpts.originalLimit = mod.options.limit;
|
|
@@ -4432,7 +4426,7 @@ async function _populatePath(model, docs, populateOptions) {
|
|
|
4432
4426
|
}
|
|
4433
4427
|
for (const arr of params) {
|
|
4434
4428
|
const mod = arr[0];
|
|
4435
|
-
if (mod.options
|
|
4429
|
+
if (mod.options?.options?._leanTransform) {
|
|
4436
4430
|
for (const doc of vals) {
|
|
4437
4431
|
mod.options.options._leanTransform(doc);
|
|
4438
4432
|
}
|
|
@@ -4987,7 +4981,7 @@ Model._applyQueryMiddleware = function _applyQueryMiddleware() {
|
|
|
4987
4981
|
return !!contexts.query;
|
|
4988
4982
|
}
|
|
4989
4983
|
if (hook.name === 'deleteOne' || hook.name === 'updateOne') {
|
|
4990
|
-
return !!contexts.query ||
|
|
4984
|
+
return !!contexts.query || utils.hasOwnKeys(contexts) === false;
|
|
4991
4985
|
}
|
|
4992
4986
|
if (hook.query != null || hook.document != null) {
|
|
4993
4987
|
return !!hook.query;
|
package/lib/mongoose.js
CHANGED
|
@@ -82,7 +82,7 @@ function Mongoose(options) {
|
|
|
82
82
|
|
|
83
83
|
// If a user creates their own Mongoose instance, give them a separate copy
|
|
84
84
|
// of the `Schema` constructor so they get separate custom types. (gh-6933)
|
|
85
|
-
if (!options
|
|
85
|
+
if (!options?.[defaultMongooseSymbol]) {
|
|
86
86
|
const _this = this;
|
|
87
87
|
this.Schema = function() {
|
|
88
88
|
this.base = _this;
|
|
@@ -308,8 +308,8 @@ Mongoose.prototype.set = function getsetOptions(key, value) {
|
|
|
308
308
|
} else if (optionKey === 'createInitialConnection') {
|
|
309
309
|
if (optionValue && !_mongoose.connection) {
|
|
310
310
|
_createDefaultConnection(_mongoose);
|
|
311
|
-
} else if (optionValue === false && _mongoose.connection
|
|
312
|
-
if (_mongoose.connection.readyState === STATES.disconnected &&
|
|
311
|
+
} else if (optionValue === false && _mongoose.connection?.[defaultConnectionSymbol]) {
|
|
312
|
+
if (_mongoose.connection.readyState === STATES.disconnected && utils.hasOwnKeys(_mongoose.connection.models) === false) {
|
|
313
313
|
_mongoose.connections.shift();
|
|
314
314
|
}
|
|
315
315
|
}
|
|
@@ -746,8 +746,8 @@ Mongoose.prototype._applyPlugins = function _applyPlugins(schema, options) {
|
|
|
746
746
|
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
|
747
747
|
|
|
748
748
|
options = options || {};
|
|
749
|
-
options.applyPluginsToDiscriminators = _mongoose.options
|
|
750
|
-
options.applyPluginsToChildSchemas = typeof
|
|
749
|
+
options.applyPluginsToDiscriminators = _mongoose.options?.applyPluginsToDiscriminators || false;
|
|
750
|
+
options.applyPluginsToChildSchemas = typeof _mongoose.options?.applyPluginsToChildSchemas === 'boolean' ?
|
|
751
751
|
_mongoose.options.applyPluginsToChildSchemas :
|
|
752
752
|
true;
|
|
753
753
|
applyPlugins(schema, _mongoose.plugins, options, '$globalPluginsApplied');
|
|
@@ -27,7 +27,7 @@ module.exports = function saveSubdocs(schema) {
|
|
|
27
27
|
|
|
28
28
|
schema.s.hooks.pre('save', async function saveSubdocsPreDeleteOne() {
|
|
29
29
|
const removedSubdocs = this.$__.removedSubdocs;
|
|
30
|
-
if (!removedSubdocs
|
|
30
|
+
if (!removedSubdocs?.length) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -41,7 +41,7 @@ module.exports = function saveSubdocs(schema) {
|
|
|
41
41
|
|
|
42
42
|
schema.s.hooks.post('save', async function saveSubdocsPostDeleteOne() {
|
|
43
43
|
const removedSubdocs = this.$__.removedSubdocs;
|
|
44
|
-
if (!removedSubdocs
|
|
44
|
+
if (!removedSubdocs?.length) {
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -39,12 +39,11 @@ function _getAtomics(doc, previous) {
|
|
|
39
39
|
|
|
40
40
|
for (const path of pathsToCheck) {
|
|
41
41
|
const val = doc.$__getValue(path);
|
|
42
|
-
if (val
|
|
43
|
-
Array.isArray(val) &&
|
|
42
|
+
if (Array.isArray(val) &&
|
|
44
43
|
utils.isMongooseDocumentArray(val) &&
|
|
45
44
|
val.length &&
|
|
46
45
|
val[arrayAtomicsSymbol] != null &&
|
|
47
|
-
|
|
46
|
+
utils.hasOwnKeys(val[arrayAtomicsSymbol])) {
|
|
48
47
|
const existing = previous.get(path) || {};
|
|
49
48
|
pathToAtomics.set(path, mergeAtomics(existing, val[arrayAtomicsSymbol]));
|
|
50
49
|
}
|
|
@@ -55,7 +54,7 @@ function _getAtomics(doc, previous) {
|
|
|
55
54
|
const path = dirt.path;
|
|
56
55
|
|
|
57
56
|
const val = dirt.value;
|
|
58
|
-
if (val
|
|
57
|
+
if (val?.[arrayAtomicsSymbol] != null && utils.hasOwnKeys(val[arrayAtomicsSymbol])) {
|
|
59
58
|
const existing = previous.get(path) || {};
|
|
60
59
|
pathToAtomics.set(path, mergeAtomics(existing, val[arrayAtomicsSymbol]));
|
|
61
60
|
}
|