Skip to content

Commit c97d91c

Browse files
committed
Merge branch '7.x'
2 parents 4d7f71d + 4a38517 commit c97d91c

27 files changed

+306
-148
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
7.6.7 / 2023-12-06
2+
==================
3+
* fix: avoid minimizing single nested subdocs if they are required #14151 #14058
4+
* fix(populate): allow deselecting discriminator key when populating #14155 #3230
5+
* fix: allow adding discriminators using Schema.prototype.discriminator() to subdocuments after defining parent schema #14131 #14109
6+
* fix(schema): avoid creating unnecessary clone of schematype in nested array so nested document arrays use correct constructor #14128 #14101
7+
* fix(populate): call transform object with single id instead of array when populating a justOne path under an array #14135 #14073
8+
* types: add back mistakenly removed findByIdAndRemove() function signature #14136 #14132
9+
110
8.0.2 / 2023-11-28
211
==================
312
* fix(populate): set populated docs in correct order when populating virtual underneath doc array with justOne #14105

docs/version-support.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ We ship all new bug fixes and features to 7.x.
1010

1111
## Mongoose 6
1212

13-
Mongoose 6.x (released August 24, 2021) is currently in legacy support.
14-
We will continue to ship bug fixes to Mongoose 6 until August 24, 2023.
15-
After August 24, 2023, we will only ship security fixes, and backport requested fixes to Mongoose 6.
13+
Mongoose 6.x (released August 24, 2021) is currently only receiving security fixes and requested bug fixes as of August 24, 2023.
1614
Please open a [bug report on GitHub](https://github.com/Automattic/mongoose/issues/new?assignees=&labels=&template=bug.yml) to request backporting a fix to Mongoose 6.
1715

1816
We are **not** actively backporting any new features from Mongoose 7 into Mongoose 6.

lib/document.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3691,8 +3691,7 @@ Document.prototype.$toObject = function(options, json) {
36913691
const schemaOptions = this.$__schema && this.$__schema.options || {};
36923692
// merge base default options with Schema's set default options if available.
36933693
// `clone` is necessary here because `utils.options` directly modifies the second input.
3694-
defaultOptions = utils.options(defaultOptions, clone(baseOptions));
3695-
defaultOptions = utils.options(defaultOptions, clone(schemaOptions[path] || {}));
3694+
defaultOptions = { ...defaultOptions, ...baseOptions, ...schemaOptions[path] };
36963695

36973696
// If options do not exist or is not an object, set it to empty object
36983697
options = utils.isPOJO(options) ? { ...options } : {};
@@ -3754,7 +3753,7 @@ Document.prototype.$toObject = function(options, json) {
37543753
}
37553754

37563755
// merge default options with input options.
3757-
options = utils.options(defaultOptions, options);
3756+
options = { ...defaultOptions, ...options };
37583757
options._isNested = true;
37593758
options.json = json;
37603759
options.minimize = _minimize;

lib/helpers/clone.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function clone(obj, options, isArrayChild) {
5454
ret = obj.toObject(options);
5555
}
5656

57-
if (options && options.minimize && isSingleNested && Object.keys(ret).length === 0) {
57+
if (options && options.minimize && !obj.constructor.$__required && isSingleNested && Object.keys(ret).length === 0) {
5858
return undefined;
5959
}
6060

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
module.exports = applyEmbeddedDiscriminators;
4+
5+
function applyEmbeddedDiscriminators(schema, seen = new WeakSet()) {
6+
if (seen.has(schema)) {
7+
return;
8+
}
9+
seen.add(schema);
10+
for (const path of Object.keys(schema.paths)) {
11+
const schemaType = schema.paths[path];
12+
if (!schemaType.schema) {
13+
continue;
14+
}
15+
applyEmbeddedDiscriminators(schemaType.schema, seen);
16+
if (!schemaType.schema._applyDiscriminators) {
17+
continue;
18+
}
19+
for (const disc of schemaType.schema._applyDiscriminators.keys()) {
20+
schemaType.discriminator(disc, schemaType.schema._applyDiscriminators.get(disc));
21+
}
22+
}
23+
}

lib/helpers/populate/assignVals.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ module.exports = function assignVals(o) {
3939
const options = o.options;
4040
const count = o.count && o.isVirtual;
4141
let i;
42+
let setValueIndex = 0;
4243

4344
function setValue(val) {
45+
++setValueIndex;
4446
if (count) {
4547
return val;
4648
}
@@ -80,11 +82,14 @@ module.exports = function assignVals(o) {
8082
return valueFilter(val[0], options, populateOptions, _allIds);
8183
} else if (o.justOne === false && !Array.isArray(val)) {
8284
return valueFilter([val], options, populateOptions, _allIds);
85+
} else if (o.justOne === true && !Array.isArray(val) && Array.isArray(_allIds)) {
86+
return valueFilter(val, options, populateOptions, val == null ? val : _allIds[setValueIndex - 1]);
8387
}
8488
return valueFilter(val, options, populateOptions, _allIds);
8589
}
8690

8791
for (i = 0; i < docs.length; ++i) {
92+
setValueIndex = 0;
8893
const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
8994
const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
9095
if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {

lib/helpers/projection/isExclusive.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ module.exports = function isExclusive(projection) {
1212
}
1313

1414
const keys = Object.keys(projection);
15-
let ki = keys.length;
1615
let exclude = null;
1716

18-
if (ki === 1 && keys[0] === '_id') {
17+
if (keys.length === 1 && keys[0] === '_id') {
1918
exclude = !projection._id;
2019
} else {
21-
while (ki--) {
20+
for (let ki = 0; ki < keys.length; ++ki) {
2221
// Does this projection explicitly define inclusion/exclusion?
2322
// Explicitly avoid `$meta` and `$slice`
2423
const key = keys[ki];

lib/model.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4300,7 +4300,7 @@ function populate(model, docs, options, callback) {
43004300
select = select.replace(excludeIdRegGlobal, ' ');
43014301
} else {
43024302
// preserve original select conditions by copying
4303-
select = utils.object.shallowCopy(select);
4303+
select = { ...select };
43044304
delete select._id;
43054305
}
43064306
}

lib/mongoose.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const sanitizeFilter = require('./helpers/query/sanitizeFilter');
3030
const isBsonType = require('./helpers/isBsonType');
3131
const MongooseError = require('./error/mongooseError');
3232
const SetOptionError = require('./error/setOptionError');
33+
const applyEmbeddedDiscriminators = require('./helpers/discriminator/applyEmbeddedDiscriminators');
3334

3435
const defaultMongooseSymbol = Symbol.for('mongoose:default');
3536

@@ -627,6 +628,8 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
627628
}
628629
}
629630

631+
applyEmbeddedDiscriminators(schema);
632+
630633
return model;
631634
};
632635

lib/query.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4791,16 +4791,14 @@ Query.prototype._castFields = function _castFields(fields) {
47914791
elemMatchKeys,
47924792
keys,
47934793
key,
4794-
out,
4795-
i;
4794+
out;
47964795

47974796
if (fields) {
47984797
keys = Object.keys(fields);
47994798
elemMatchKeys = [];
4800-
i = keys.length;
48014799

48024800
// collect $elemMatch args
4803-
while (i--) {
4801+
for (let i = 0; i < keys.length; ++i) {
48044802
key = keys[i];
48054803
if (fields[key].$elemMatch) {
48064804
selected || (selected = {});
@@ -4819,8 +4817,7 @@ Query.prototype._castFields = function _castFields(fields) {
48194817
}
48204818

48214819
// apply the casted field args
4822-
i = elemMatchKeys.length;
4823-
while (i--) {
4820+
for (let i = 0; i < elemMatchKeys.length; ++i) {
48244821
key = elemMatchKeys[i];
48254822
fields[key] = out[key];
48264823
}

lib/queryHelpers.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,12 @@ exports.applyPaths = function applyPaths(fields, schema) {
180180
if (!isDefiningProjection(field)) {
181181
continue;
182182
}
183-
// `_id: 1, name: 0` is a mixed inclusive/exclusive projection in
184-
// MongoDB 4.0 and earlier, but not in later versions.
185183
if (keys[keyIndex] === '_id' && keys.length > 1) {
186184
continue;
187185
}
186+
if (keys[keyIndex] === schema.options.discriminatorKey && keys.length > 1 && field != null && !field) {
187+
continue;
188+
}
188189
exclude = !field;
189190
break;
190191
}

lib/schema.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ Schema.prototype.defaultOptions = function(options) {
560560
const strict = 'strict' in baseOptions ? baseOptions.strict : true;
561561
const strictQuery = 'strictQuery' in baseOptions ? baseOptions.strictQuery : false;
562562
const id = 'id' in baseOptions ? baseOptions.id : true;
563-
options = utils.options({
563+
options = {
564564
strict,
565565
strictQuery,
566566
bufferCommands: true,
@@ -577,8 +577,9 @@ Schema.prototype.defaultOptions = function(options) {
577577
// the following are only applied at construction time
578578
_id: true,
579579
id: id,
580-
typeKey: 'type'
581-
}, clone(options));
580+
typeKey: 'type',
581+
...options
582+
};
582583

583584
if (options.versionKey && typeof options.versionKey !== 'string') {
584585
throw new MongooseError('`versionKey` must be falsy or string, got `' + (typeof options.versionKey) + '`');

lib/schema/bigint.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
const CastError = require('../error/cast');
88
const SchemaType = require('../schemaType');
99
const castBigInt = require('../cast/bigint');
10-
const utils = require('../utils');
1110

1211
/**
1312
* BigInt SchemaType constructor.
@@ -177,12 +176,13 @@ SchemaBigInt.prototype.cast = function(value) {
177176
* ignore
178177
*/
179178

180-
SchemaBigInt.$conditionalHandlers = utils.options(SchemaType.prototype.$conditionalHandlers, {
179+
SchemaBigInt.$conditionalHandlers = {
180+
...SchemaType.prototype.$conditionalHandlers,
181181
$gt: handleSingle,
182182
$gte: handleSingle,
183183
$lt: handleSingle,
184184
$lte: handleSingle
185-
});
185+
};
186186

187187
/*!
188188
* ignore

lib/schema/boolean.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
const CastError = require('../error/cast');
88
const SchemaType = require('../schemaType');
99
const castBoolean = require('../cast/boolean');
10-
const utils = require('../utils');
1110

1211
/**
1312
* Boolean SchemaType constructor.
@@ -235,8 +234,7 @@ SchemaBoolean.prototype.cast = function(value) {
235234
}
236235
};
237236

238-
SchemaBoolean.$conditionalHandlers =
239-
utils.options(SchemaType.prototype.$conditionalHandlers, {});
237+
SchemaBoolean.$conditionalHandlers = { ...SchemaType.prototype.$conditionalHandlers };
240238

241239
/**
242240
* Casts contents for queries.

lib/schema/buffer.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,17 @@ function handleSingle(val, context) {
250250
return this.castForQuery(null, val, context);
251251
}
252252

253-
SchemaBuffer.prototype.$conditionalHandlers =
254-
utils.options(SchemaType.prototype.$conditionalHandlers, {
255-
$bitsAllClear: handleBitwiseOperator,
256-
$bitsAnyClear: handleBitwiseOperator,
257-
$bitsAllSet: handleBitwiseOperator,
258-
$bitsAnySet: handleBitwiseOperator,
259-
$gt: handleSingle,
260-
$gte: handleSingle,
261-
$lt: handleSingle,
262-
$lte: handleSingle
263-
});
253+
SchemaBuffer.prototype.$conditionalHandlers = {
254+
...SchemaType.prototype.$conditionalHandlers,
255+
$bitsAllClear: handleBitwiseOperator,
256+
$bitsAnyClear: handleBitwiseOperator,
257+
$bitsAllSet: handleBitwiseOperator,
258+
$bitsAnySet: handleBitwiseOperator,
259+
$gt: handleSingle,
260+
$gte: handleSingle,
261+
$lt: handleSingle,
262+
$lte: handleSingle
263+
};
264264

265265
/**
266266
* Casts contents for queries.

lib/schema/date.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -388,13 +388,13 @@ function handleSingle(val) {
388388
return this.cast(val);
389389
}
390390

391-
SchemaDate.prototype.$conditionalHandlers =
392-
utils.options(SchemaType.prototype.$conditionalHandlers, {
393-
$gt: handleSingle,
394-
$gte: handleSingle,
395-
$lt: handleSingle,
396-
$lte: handleSingle
397-
});
391+
SchemaDate.prototype.$conditionalHandlers = {
392+
...SchemaType.prototype.$conditionalHandlers,
393+
$gt: handleSingle,
394+
$gte: handleSingle,
395+
$lt: handleSingle,
396+
$lte: handleSingle
397+
};
398398

399399

400400
/**

lib/schema/decimal128.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
const SchemaType = require('../schemaType');
88
const CastError = SchemaType.CastError;
99
const castDecimal128 = require('../cast/decimal128');
10-
const utils = require('../utils');
1110
const isBsonType = require('../helpers/isBsonType');
1211

1312
/**
@@ -214,13 +213,13 @@ function handleSingle(val) {
214213
return this.cast(val);
215214
}
216215

217-
SchemaDecimal128.prototype.$conditionalHandlers =
218-
utils.options(SchemaType.prototype.$conditionalHandlers, {
219-
$gt: handleSingle,
220-
$gte: handleSingle,
221-
$lt: handleSingle,
222-
$lte: handleSingle
223-
});
216+
SchemaDecimal128.prototype.$conditionalHandlers = {
217+
...SchemaType.prototype.$conditionalHandlers,
218+
$gt: handleSingle,
219+
$gte: handleSingle,
220+
$lt: handleSingle,
221+
$lte: handleSingle
222+
};
224223

225224
/*!
226225
* Module exports.

lib/schema/documentArray.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@ function SchemaDocumentArray(key, schema, options, schemaOptions) {
8888

8989
this.$embeddedSchemaType.caster = this.Constructor;
9090
this.$embeddedSchemaType.schema = this.schema;
91-
92-
if (schema._applyDiscriminators != null && !options?._skipApplyDiscriminators) {
93-
for (const disc of schema._applyDiscriminators.keys()) {
94-
this.discriminator(disc, schema._applyDiscriminators.get(disc));
95-
}
96-
}
9791
}
9892

9993
/**
@@ -528,7 +522,7 @@ SchemaDocumentArray.prototype.cast = function(value, doc, init, prev, options) {
528522

529523
SchemaDocumentArray.prototype.clone = function() {
530524
const options = Object.assign({}, this.options);
531-
const schematype = new this.constructor(this.path, this.schema, { ...options, _skipApplyDiscriminators: true }, this.schemaOptions);
525+
const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
532526
schematype.validators = this.validators.slice();
533527
if (this.requiredValidator !== undefined) {
534528
schematype.requiredValidator = this.requiredValidator;

lib/schema/number.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -399,18 +399,18 @@ function handleArray(val) {
399399
});
400400
}
401401

402-
SchemaNumber.prototype.$conditionalHandlers =
403-
utils.options(SchemaType.prototype.$conditionalHandlers, {
404-
$bitsAllClear: handleBitwiseOperator,
405-
$bitsAnyClear: handleBitwiseOperator,
406-
$bitsAllSet: handleBitwiseOperator,
407-
$bitsAnySet: handleBitwiseOperator,
408-
$gt: handleSingle,
409-
$gte: handleSingle,
410-
$lt: handleSingle,
411-
$lte: handleSingle,
412-
$mod: handleArray
413-
});
402+
SchemaNumber.prototype.$conditionalHandlers = {
403+
...SchemaType.prototype.$conditionalHandlers,
404+
$bitsAllClear: handleBitwiseOperator,
405+
$bitsAnyClear: handleBitwiseOperator,
406+
$bitsAllSet: handleBitwiseOperator,
407+
$bitsAnySet: handleBitwiseOperator,
408+
$gt: handleSingle,
409+
$gte: handleSingle,
410+
$lt: handleSingle,
411+
$lte: handleSingle,
412+
$mod: handleArray
413+
};
414414

415415
/**
416416
* Casts contents for queries.

0 commit comments

Comments
 (0)