Skip to content

Commit

Permalink
Merge branch '7.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Dec 6, 2023
2 parents 4d7f71d + 4a38517 commit c97d91c
Show file tree
Hide file tree
Showing 27 changed files with 306 additions and 148 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
7.6.7 / 2023-12-06
==================
* fix: avoid minimizing single nested subdocs if they are required #14151 #14058
* fix(populate): allow deselecting discriminator key when populating #14155 #3230
* fix: allow adding discriminators using Schema.prototype.discriminator() to subdocuments after defining parent schema #14131 #14109
* fix(schema): avoid creating unnecessary clone of schematype in nested array so nested document arrays use correct constructor #14128 #14101
* fix(populate): call transform object with single id instead of array when populating a justOne path under an array #14135 #14073
* types: add back mistakenly removed findByIdAndRemove() function signature #14136 #14132

8.0.2 / 2023-11-28
==================
* fix(populate): set populated docs in correct order when populating virtual underneath doc array with justOne #14105
Expand Down
4 changes: 1 addition & 3 deletions docs/version-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ We ship all new bug fixes and features to 7.x.

## Mongoose 6

Mongoose 6.x (released August 24, 2021) is currently in legacy support.
We will continue to ship bug fixes to Mongoose 6 until August 24, 2023.
After August 24, 2023, we will only ship security fixes, and backport requested fixes to Mongoose 6.
Mongoose 6.x (released August 24, 2021) is currently only receiving security fixes and requested bug fixes as of August 24, 2023.
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.

We are **not** actively backporting any new features from Mongoose 7 into Mongoose 6.
Expand Down
5 changes: 2 additions & 3 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -3691,8 +3691,7 @@ Document.prototype.$toObject = function(options, json) {
const schemaOptions = this.$__schema && this.$__schema.options || {};
// merge base default options with Schema's set default options if available.
// `clone` is necessary here because `utils.options` directly modifies the second input.
defaultOptions = utils.options(defaultOptions, clone(baseOptions));
defaultOptions = utils.options(defaultOptions, clone(schemaOptions[path] || {}));
defaultOptions = { ...defaultOptions, ...baseOptions, ...schemaOptions[path] };

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

// merge default options with input options.
options = utils.options(defaultOptions, options);
options = { ...defaultOptions, ...options };
options._isNested = true;
options.json = json;
options.minimize = _minimize;
Expand Down
2 changes: 1 addition & 1 deletion lib/helpers/clone.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function clone(obj, options, isArrayChild) {
ret = obj.toObject(options);
}

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

Expand Down
23 changes: 23 additions & 0 deletions lib/helpers/discriminator/applyEmbeddedDiscriminators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

module.exports = applyEmbeddedDiscriminators;

function applyEmbeddedDiscriminators(schema, seen = new WeakSet()) {
if (seen.has(schema)) {
return;
}
seen.add(schema);
for (const path of Object.keys(schema.paths)) {
const schemaType = schema.paths[path];
if (!schemaType.schema) {
continue;
}
applyEmbeddedDiscriminators(schemaType.schema, seen);
if (!schemaType.schema._applyDiscriminators) {
continue;
}
for (const disc of schemaType.schema._applyDiscriminators.keys()) {
schemaType.discriminator(disc, schemaType.schema._applyDiscriminators.get(disc));
}
}
}
5 changes: 5 additions & 0 deletions lib/helpers/populate/assignVals.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ module.exports = function assignVals(o) {
const options = o.options;
const count = o.count && o.isVirtual;
let i;
let setValueIndex = 0;

function setValue(val) {
++setValueIndex;
if (count) {
return val;
}
Expand Down Expand Up @@ -80,11 +82,14 @@ module.exports = function assignVals(o) {
return valueFilter(val[0], options, populateOptions, _allIds);
} else if (o.justOne === false && !Array.isArray(val)) {
return valueFilter([val], options, populateOptions, _allIds);
} else if (o.justOne === true && !Array.isArray(val) && Array.isArray(_allIds)) {
return valueFilter(val, options, populateOptions, val == null ? val : _allIds[setValueIndex - 1]);
}
return valueFilter(val, options, populateOptions, _allIds);
}

for (i = 0; i < docs.length; ++i) {
setValueIndex = 0;
const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {
Expand Down
5 changes: 2 additions & 3 deletions lib/helpers/projection/isExclusive.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ module.exports = function isExclusive(projection) {
}

const keys = Object.keys(projection);
let ki = keys.length;
let exclude = null;

if (ki === 1 && keys[0] === '_id') {
if (keys.length === 1 && keys[0] === '_id') {
exclude = !projection._id;
} else {
while (ki--) {
for (let ki = 0; ki < keys.length; ++ki) {
// Does this projection explicitly define inclusion/exclusion?
// Explicitly avoid `$meta` and `$slice`
const key = keys[ki];
Expand Down
2 changes: 1 addition & 1 deletion lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -4300,7 +4300,7 @@ function populate(model, docs, options, callback) {
select = select.replace(excludeIdRegGlobal, ' ');
} else {
// preserve original select conditions by copying
select = utils.object.shallowCopy(select);
select = { ...select };
delete select._id;
}
}
Expand Down
3 changes: 3 additions & 0 deletions lib/mongoose.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const sanitizeFilter = require('./helpers/query/sanitizeFilter');
const isBsonType = require('./helpers/isBsonType');
const MongooseError = require('./error/mongooseError');
const SetOptionError = require('./error/setOptionError');
const applyEmbeddedDiscriminators = require('./helpers/discriminator/applyEmbeddedDiscriminators');

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

Expand Down Expand Up @@ -627,6 +628,8 @@ Mongoose.prototype._model = function(name, schema, collection, options) {
}
}

applyEmbeddedDiscriminators(schema);

return model;
};

Expand Down
9 changes: 3 additions & 6 deletions lib/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -4791,16 +4791,14 @@ Query.prototype._castFields = function _castFields(fields) {
elemMatchKeys,
keys,
key,
out,
i;
out;

if (fields) {
keys = Object.keys(fields);
elemMatchKeys = [];
i = keys.length;

// collect $elemMatch args
while (i--) {
for (let i = 0; i < keys.length; ++i) {
key = keys[i];
if (fields[key].$elemMatch) {
selected || (selected = {});
Expand All @@ -4819,8 +4817,7 @@ Query.prototype._castFields = function _castFields(fields) {
}

// apply the casted field args
i = elemMatchKeys.length;
while (i--) {
for (let i = 0; i < elemMatchKeys.length; ++i) {
key = elemMatchKeys[i];
fields[key] = out[key];
}
Expand Down
5 changes: 3 additions & 2 deletions lib/queryHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,12 @@ exports.applyPaths = function applyPaths(fields, schema) {
if (!isDefiningProjection(field)) {
continue;
}
// `_id: 1, name: 0` is a mixed inclusive/exclusive projection in
// MongoDB 4.0 and earlier, but not in later versions.
if (keys[keyIndex] === '_id' && keys.length > 1) {
continue;
}
if (keys[keyIndex] === schema.options.discriminatorKey && keys.length > 1 && field != null && !field) {
continue;
}
exclude = !field;
break;
}
Expand Down
7 changes: 4 additions & 3 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ Schema.prototype.defaultOptions = function(options) {
const strict = 'strict' in baseOptions ? baseOptions.strict : true;
const strictQuery = 'strictQuery' in baseOptions ? baseOptions.strictQuery : false;
const id = 'id' in baseOptions ? baseOptions.id : true;
options = utils.options({
options = {
strict,
strictQuery,
bufferCommands: true,
Expand All @@ -577,8 +577,9 @@ Schema.prototype.defaultOptions = function(options) {
// the following are only applied at construction time
_id: true,
id: id,
typeKey: 'type'
}, clone(options));
typeKey: 'type',
...options
};

if (options.versionKey && typeof options.versionKey !== 'string') {
throw new MongooseError('`versionKey` must be falsy or string, got `' + (typeof options.versionKey) + '`');
Expand Down
6 changes: 3 additions & 3 deletions lib/schema/bigint.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
const CastError = require('../error/cast');
const SchemaType = require('../schemaType');
const castBigInt = require('../cast/bigint');
const utils = require('../utils');

/**
* BigInt SchemaType constructor.
Expand Down Expand Up @@ -177,12 +176,13 @@ SchemaBigInt.prototype.cast = function(value) {
* ignore
*/

SchemaBigInt.$conditionalHandlers = utils.options(SchemaType.prototype.$conditionalHandlers, {
SchemaBigInt.$conditionalHandlers = {
...SchemaType.prototype.$conditionalHandlers,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
});
};

/*!
* ignore
Expand Down
4 changes: 1 addition & 3 deletions lib/schema/boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
const CastError = require('../error/cast');
const SchemaType = require('../schemaType');
const castBoolean = require('../cast/boolean');
const utils = require('../utils');

/**
* Boolean SchemaType constructor.
Expand Down Expand Up @@ -235,8 +234,7 @@ SchemaBoolean.prototype.cast = function(value) {
}
};

SchemaBoolean.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {});
SchemaBoolean.$conditionalHandlers = { ...SchemaType.prototype.$conditionalHandlers };

/**
* Casts contents for queries.
Expand Down
22 changes: 11 additions & 11 deletions lib/schema/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,17 +250,17 @@ function handleSingle(val, context) {
return this.castForQuery(null, val, context);
}

SchemaBuffer.prototype.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {
$bitsAllClear: handleBitwiseOperator,
$bitsAnyClear: handleBitwiseOperator,
$bitsAllSet: handleBitwiseOperator,
$bitsAnySet: handleBitwiseOperator,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
});
SchemaBuffer.prototype.$conditionalHandlers = {
...SchemaType.prototype.$conditionalHandlers,
$bitsAllClear: handleBitwiseOperator,
$bitsAnyClear: handleBitwiseOperator,
$bitsAllSet: handleBitwiseOperator,
$bitsAnySet: handleBitwiseOperator,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
};

/**
* Casts contents for queries.
Expand Down
14 changes: 7 additions & 7 deletions lib/schema/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,13 @@ function handleSingle(val) {
return this.cast(val);
}

SchemaDate.prototype.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
});
SchemaDate.prototype.$conditionalHandlers = {
...SchemaType.prototype.$conditionalHandlers,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
};


/**
Expand Down
15 changes: 7 additions & 8 deletions lib/schema/decimal128.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
const SchemaType = require('../schemaType');
const CastError = SchemaType.CastError;
const castDecimal128 = require('../cast/decimal128');
const utils = require('../utils');
const isBsonType = require('../helpers/isBsonType');

/**
Expand Down Expand Up @@ -214,13 +213,13 @@ function handleSingle(val) {
return this.cast(val);
}

SchemaDecimal128.prototype.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
});
SchemaDecimal128.prototype.$conditionalHandlers = {
...SchemaType.prototype.$conditionalHandlers,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle
};

/*!
* Module exports.
Expand Down
8 changes: 1 addition & 7 deletions lib/schema/documentArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ function SchemaDocumentArray(key, schema, options, schemaOptions) {

this.$embeddedSchemaType.caster = this.Constructor;
this.$embeddedSchemaType.schema = this.schema;

if (schema._applyDiscriminators != null && !options?._skipApplyDiscriminators) {
for (const disc of schema._applyDiscriminators.keys()) {
this.discriminator(disc, schema._applyDiscriminators.get(disc));
}
}
}

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

SchemaDocumentArray.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(this.path, this.schema, { ...options, _skipApplyDiscriminators: true }, this.schemaOptions);
const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
schematype.validators = this.validators.slice();
if (this.requiredValidator !== undefined) {
schematype.requiredValidator = this.requiredValidator;
Expand Down
24 changes: 12 additions & 12 deletions lib/schema/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,18 +399,18 @@ function handleArray(val) {
});
}

SchemaNumber.prototype.$conditionalHandlers =
utils.options(SchemaType.prototype.$conditionalHandlers, {
$bitsAllClear: handleBitwiseOperator,
$bitsAnyClear: handleBitwiseOperator,
$bitsAllSet: handleBitwiseOperator,
$bitsAnySet: handleBitwiseOperator,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle,
$mod: handleArray
});
SchemaNumber.prototype.$conditionalHandlers = {
...SchemaType.prototype.$conditionalHandlers,
$bitsAllClear: handleBitwiseOperator,
$bitsAnyClear: handleBitwiseOperator,
$bitsAllSet: handleBitwiseOperator,
$bitsAnySet: handleBitwiseOperator,
$gt: handleSingle,
$gte: handleSingle,
$lt: handleSingle,
$lte: handleSingle,
$mod: handleArray
};

/**
* Casts contents for queries.
Expand Down
Loading

0 comments on commit c97d91c

Please sign in to comment.