Skip to content

Commit 37d6051

Browse files
committed
Merge branch '7.x'
2 parents 401fae6 + db7a983 commit 37d6051

24 files changed

+349
-21
lines changed

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,34 @@
1+
7.6.5 / 2023-11-14
2+
==================
3+
* fix: handle update validators and single nested doc with numeric paths #14066 #13977
4+
* fix: handle recursive schema array in discriminator definition #14068 #14055
5+
* fix: diffIndexes treats namespace error as empty #14048 #14029
6+
* docs(migrating_to_7): add note about requiring new with ObjectId #14021 #14020
7+
8+
6.12.3 / 2023-11-07
9+
===================
10+
* fix(ChangeStream): correctly handle hydrate option when using change stream as stream instead of iterator #14052
11+
* fix(schema): fix dangling reference to virtual in tree after `removeVirtual()` #14019 #13085
12+
* fix(document): avoid unmarking modified on nested path if no initial value stored and already modified #14053 #14024
13+
* fix(document): consistently avoid marking subpaths of nested paths as modified #14053 #14022
14+
115
8.0.0 / 2023-10-31
216
==================
317
* docs: add version support notes for Mongoose 8, including EOL date for Mongoose 6
418

19+
7.6.4 / 2023-10-30
20+
==================
21+
* fix(connection): retain modified status for documents created outside a transaction during transaction retries #14017 #13973
22+
* fix(schema): handle recursive schemas in discriminator definitions #14011 #13978
23+
* fix: handle casting $or underneath $elemMatch #14007 #13974
24+
* fix(populate): allow using options: { strictPopulate: false } to disable strict populate #13863
25+
* docs: fix differences between sample codes and documentation #13998 [suzuki](https://github.com/suzuki)
26+
* docs: fix missing import and change wrong variable name #13992 [suzuki](https://github.com/suzuki)
27+
28+
6.12.2 / 2023-10-25
29+
===================
30+
* fix: add fullPath to ValidatorProps #13995 [Freezystem](https://github.com/Freezystem)
31+
532
8.0.0-rc0 / 2023-10-24
633
======================
734
* BREAKING CHANGE: use MongoDB node driver 6, drop support for rawResult option and findOneAndRemove() #13753
@@ -37,6 +64,11 @@
3764
* types(models): add cleaner type definitions for insertMany() with no generics to prevent errors when using insertMany() in generic classes #13964 #13957
3865
* types(schematypes): allow defining map path using type: 'Map' in addition to type: Map #13960 #13755
3966

67+
6.12.1 / 2023-10-12
68+
===================
69+
* fix(mongoose): correctly handle global applyPluginsToChildSchemas option #13945 #13887 [hasezoey](https://github.com/hasezoey)
70+
* fix: Document.prototype.isModified support for a string of keys as first parameter #13940 #13674 [k-chop](https://github.com/k-chop)
71+
4072
7.6.1 / 2023-10-09
4173
==================
4274
* fix: bump bson to match mongodb@5.9.0 exactly #13947 [hasezoey](https://github.com/hasezoey)

docs/migrating_to_7.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ If you're still on Mongoose 5.x, please read the [Mongoose 5.x to 6.x migration
1515
* [Removed `remove()`](#removed-remove)
1616
* [Dropped callback support](#dropped-callback-support)
1717
* [Removed `update()`](#removed-update)
18+
* [ObjectId requires `new`](#objectid-requires-new)
1819
* [Discriminator schemas use base schema options by default](#discriminator-schemas-use-base-schema-options-by-default)
1920
* [Removed `castForQueryWrapper()`, updated `castForQuery()` signature](#removed-castforquerywrapper)
2021
* [Copy schema options in `Schema.prototype.add()`](#copy-schema-options-in-schema-prototype-add)
@@ -178,6 +179,23 @@ await Model.updateOne(filter, update);
178179
await doc.updateOne(update);
179180
```
180181

182+
<h2 id="objectid-requires-new"><a href="#objectid-requires-new">ObjectId requires <code>new</code></a></h2>
183+
184+
In Mongoose 6 and older, you could define a new ObjectId without using the `new` keyword:
185+
186+
```javascript
187+
// Works in Mongoose 6
188+
// Throws "Class constructor ObjectId cannot be invoked without 'new'" in Mongoose 7
189+
const oid = mongoose.Types.ObjectId('0'.repeat(24));
190+
```
191+
192+
In Mongoose 7, `ObjectId` is now a [JavaScript class](https://masteringjs.io/tutorials/fundamentals/class), so you need to use the `new` keyword.
193+
194+
```javascript
195+
// Works in Mongoose 6 and Mongoose 7
196+
const oid = new mongoose.Types.ObjectId('0'.repeat(24));
197+
```
198+
181199
<h2 id="discriminator-schemas-use-base-schema-options-by-default"><a href="#discriminator-schemas-use-base-schema-options-by-default">Discriminator schemas use base schema options by default</a></h2>
182200

183201
When you use `Model.discriminator()`, Mongoose will now use the discriminator base schema's options by default.

docs/plugins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const playerSchema = new Schema({ /* ... */ });
4444
playerSchema.plugin(loadedAtPlugin);
4545
```
4646

47-
We just added last-modified behavior to both our `Game` and `Player` schemas and declared an index on the `lastMod` path of our Games to boot. Not bad for a few lines of code.
47+
We just added loaded-time behavior to both our `Game` and `Player` schemas and declared an index on the `loadedAt` path of our Games to boot. Not bad for a few lines of code.
4848

4949
<h2 id="global"><a href="#global">Global Plugins</a></h2>
5050

lib/connection.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,10 @@ function _resetSessionDocuments(session) {
563563
doc.$__.activePaths.states.modify = {};
564564
}
565565
for (const path of state.modifiedPaths) {
566+
const currentState = doc.$__.activePaths.paths[path];
567+
if (currentState != null) {
568+
delete doc.$__.activePaths[currentState][path];
569+
}
566570
doc.$__.activePaths.paths[path] = 'modify';
567571
doc.$__.activePaths.states.modify[path] = true;
568572
}

lib/cursor/changeStream.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ class ChangeStream extends EventEmitter {
8989
if (ev === 'error' && this.closed) {
9090
return;
9191
}
92+
if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
93+
data.fullDocument = this.options.model.hydrate(data.fullDocument);
94+
}
9295
this.emit(ev, data);
9396
});
9497
});

lib/document.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const scopeSymbol = require('./helpers/symbols').scopeSymbol;
5454
const schemaMixedSymbol = require('./schema/symbols').schemaMixedSymbol;
5555
const parentPaths = require('./helpers/path/parentPaths');
5656
const getDeepestSubdocumentForPath = require('./helpers/document/getDeepestSubdocumentForPath');
57+
const sessionNewDocuments = require('./helpers/symbols').sessionNewDocuments;
5758

5859
let DocumentArray;
5960
let MongooseArray;
@@ -1181,6 +1182,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
11811182
this.invalidate(path, new MongooseError.CastError('Object', val, path));
11821183
return this;
11831184
}
1185+
const wasModified = this.$isModified(path);
11841186
const hasInitialVal = this.$__.savedState != null && this.$__.savedState.hasOwnProperty(path);
11851187
if (this.$__.savedState != null && !this.$isNew && !this.$__.savedState.hasOwnProperty(path)) {
11861188
const initialVal = this.$__getValue(path);
@@ -1203,9 +1205,11 @@ Document.prototype.$set = function $set(path, val, type, options) {
12031205

12041206
this.$__setValue(path, {});
12051207
for (const key of keys) {
1206-
this.$set(path + '.' + key, val[key], constructing, options);
1208+
this.$set(path + '.' + key, val[key], constructing, { ...options, _skipMarkModified: true });
12071209
}
1208-
if (priorVal != null && utils.deepEqual(hasInitialVal ? this.$__.savedState[path] : priorVal, val)) {
1210+
if (priorVal != null &&
1211+
(!wasModified || hasInitialVal) &&
1212+
utils.deepEqual(hasInitialVal ? this.$__.savedState[path] : priorVal, val)) {
12091213
this.unmarkModified(path);
12101214
} else {
12111215
this.markModified(path);
@@ -1475,7 +1479,16 @@ Document.prototype.$set = function $set(path, val, type, options) {
14751479

14761480
this.$__set(pathToMark, path, options, constructing, parts, schema, val, priorVal);
14771481

1478-
if (savedState != null && savedState.hasOwnProperty(savedStatePath) && utils.deepEqual(val, savedState[savedStatePath])) {
1482+
const isInTransaction = !!this.$__.session?.transaction;
1483+
const isModifiedWithinTransaction = this.$__.session &&
1484+
this.$__.session[sessionNewDocuments] &&
1485+
this.$__.session[sessionNewDocuments].has(this) &&
1486+
this.$__.session[sessionNewDocuments].get(this).modifiedPaths &&
1487+
!this.$__.session[sessionNewDocuments].get(this).modifiedPaths.has(savedStatePath);
1488+
if (savedState != null &&
1489+
savedState.hasOwnProperty(savedStatePath) &&
1490+
(!isInTransaction || isModifiedWithinTransaction) &&
1491+
utils.deepEqual(val, savedState[savedStatePath])) {
14791492
this.unmarkModified(path);
14801493
}
14811494
}

lib/helpers/populate/getModelsMapForPopulate.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
4545
let allSchemaTypes = getSchemaTypes(model, modelSchema, null, options.path);
4646
allSchemaTypes = Array.isArray(allSchemaTypes) ? allSchemaTypes : [allSchemaTypes].filter(v => v != null);
4747

48-
if (allSchemaTypes.length === 0 && options.strictPopulate !== false && options._localModel != null) {
48+
const isStrictPopulateDisabled = options.strictPopulate === false || options.options?.strictPopulate === false;
49+
if (!isStrictPopulateDisabled && allSchemaTypes.length === 0 && options._localModel != null) {
4950
return new StrictPopulate(options._fullPath || options.path);
5051
}
5152

lib/model.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4160,9 +4160,7 @@ Model.populate = async function populate(docs, paths) {
41604160
if (typeof paths === 'function' || typeof arguments[2] === 'function') {
41614161
throw new MongooseError('Model.populate() no longer accepts a callback');
41624162
}
4163-
41644163
const _this = this;
4165-
41664164
// normalized paths
41674165
paths = utils.populate(paths);
41684166
// data that should persist across subPopulate calls

lib/query.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2273,7 +2273,6 @@ Query.prototype._find = async function _find() {
22732273
_completeManyLean(_this.model.schema, docs, null, completeManyOptions) :
22742274
completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions);
22752275
}
2276-
22772276
const pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions);
22782277

22792278
if (mongooseOptions.lean) {

lib/schema.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,9 @@ Schema.prototype._clone = function _clone(Constructor) {
412412
s.s.hooks = this.s.hooks.clone();
413413

414414
s.tree = clone(this.tree);
415-
s.paths = clone(this.paths);
415+
s.paths = Object.fromEntries(
416+
Object.entries(this.paths).map(([key, value]) => ([key, value.clone()]))
417+
);
416418
s.nested = clone(this.nested);
417419
s.subpaths = clone(this.subpaths);
418420
for (const schemaType of Object.values(s.paths)) {
@@ -2573,7 +2575,7 @@ Schema.prototype._getSchema = function(path) {
25732575
if (parts[p] === '$' || isArrayFilter(parts[p])) {
25742576
if (p + 1 === parts.length) {
25752577
// comments.$
2576-
return foundschema;
2578+
return foundschema.$embeddedSchemaType;
25772579
}
25782580
// comments.$.comments.$.title
25792581
ret = search(parts.slice(p + 1), foundschema.schema);

0 commit comments

Comments
 (0)