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 Sep 17, 2024
2 parents 8330f1e + 3cfd3f6 commit 75e1dd8
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 10 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
* fix: fix missing Aggregate re-exports for ESM #14886 [wongsean](https://github.com/wongsean)
* types(document): add generic param to depopulate() to allow updating properties #14891 #14876

6.13.2 / 2024-09-12
===================
* fix(document): make set() respect merge option on deeply nested objects #14870 #14878

8.6.2 / 2024-09-11
==================
* fix: make set merge deeply nested objects #14870 #14861 [ianHeydoc](https://github.com/ianHeydoc)
Expand Down Expand Up @@ -114,6 +118,7 @@
==================
* feat(model): add throwOnValidationError option for opting into getting MongooseBulkWriteError if all valid operations succeed in bulkWrite() and insertMany() #14599 #14587 #14572 #13410

<<<<<<< HEAD
8.4.3 / 2024-06-17
==================
* fix: remove 0x flamegraph files from release
Expand All @@ -126,6 +131,11 @@
* fix(connection): fix up some inconsistencies in operation-end event and add to docs #14659 #14648
* types: avoid inferring Boolean, Buffer, ObjectId as Date in schema definitions under certain circumstances #14667 #14630
* docs: add note about parallelism in transations #14647 [fiws](https://github.com/fiws)
=======
6.13.1 / 2024-09-06
===================
* fix: remove empty $and, $or, $not that were made empty by scrict mode #14749 #13086 [0x0a0d](https://github.com/0x0a0d)
>>>>>>> 7.x

6.13.0 / 2024-06-06
===================
Expand Down Expand Up @@ -629,7 +639,7 @@
==================
* perf: speed up mapOfSubdocs benchmark by 4x by avoiding unnecessary O(n^2) loop in getPathsToValidate() #13614
* feat: upgrade to MongoDB Node.js driver 5.7.0 #13591
* feat: add `id` setter which allows modifying `_id` by setting `id` (Note this change was reverted in Mongoose 8) #13517
* BREAKING CHANGE: add `id` setter which allows modifying `_id` by setting `id` (Note this change was originally shipped as a `feat`, but later reverted in Mongoose 8 due to compatibility issues) #13517
* feat: support generating custom cast error message with a function #13608 #3162
* feat(query): support MongoDB driver's includeResultMetadata option for findOneAndUpdate #13584 #13539
* feat(connection): add Connection.prototype.removeDb() for removing a related connection #13580 #11821
Expand Down
11 changes: 4 additions & 7 deletions docs/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ In document middleware functions, `this` refers to the document. To access the m

* [validate](api/document.html#document_Document-validate)
* [save](api/model.html#model_Model-save)
* [remove](api/model.html#model_Model-remove)
* [updateOne](api/document.html#document_Document-updateOne)
* [deleteOne](api/model.html#model_Model-deleteOne)
* [init](api/document.html#document_Document-init) (note: init hooks are [synchronous](#synchronous))
Expand All @@ -50,7 +49,6 @@ In query middleware functions, `this` refers to the query.
* [findOneAndDelete](api/query.html#query_Query-findOneAndDelete)
* [findOneAndReplace](api/query.html#query_Query-findOneAndReplace)
* [findOneAndUpdate](api/query.html#query_Query-findOneAndUpdate)
* [remove](api/model.html#model_Model-remove)
* [replaceOne](api/query.html#query_Query-replaceOne)
* [updateOne](api/query.html#query_Query-updateOne)
* [updateMany](api/query.html#query_Query-updateMany)
Expand Down Expand Up @@ -87,7 +85,6 @@ Here are the possible strings that can be passed to `pre()`
* findOneAndUpdate
* init
* insertMany
* remove
* replaceOne
* save
* update
Expand Down Expand Up @@ -400,11 +397,11 @@ Mongoose has both query and document hooks for `deleteOne()`.
```javascript
schema.pre('deleteOne', function() { console.log('Removing!'); });

// Does **not** print "Removing!". Document middleware for `remove` is not executed by default
// Does **not** print "Removing!". Document middleware for `deleteOne` is not executed by default
await doc.deleteOne();

// Prints "Removing!"
Model.remove();
await Model.deleteOne();
```

You can pass options to [`Schema.pre()`](api.html#schema_Schema-pre)
Expand All @@ -418,8 +415,8 @@ schema.pre('deleteOne', { document: true, query: false }, function() {
console.log('Deleting doc!');
});

// Only query middleware. This will get called when you do `Model.remove()`
// but not `doc.remove()`.
// Only query middleware. This will get called when you do `Model.deleteOne()`
// but not `doc.deleteOne()`.
schema.pre('deleteOne', { query: true, document: false }, function() {
console.log('Deleting!');
});
Expand Down
2 changes: 1 addition & 1 deletion docs/subdocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ doc.child;
```

<ul class="toc">
<li><a href="#what-is-a-subdocument-">What is a Subdocument?</a></li>
<li><a href="#what-is-a-subdocument">What is a Subdocument?</a></li>
<li><a href="#subdocuments-versus-nested-paths">Subdocuments versus Nested Paths</a></li>
<li><a href="#subdocument-defaults">Subdocument Defaults</a></li>
<li><a href="#finding-a-subdocument">Finding a Subdocument</a></li>
Expand Down
12 changes: 11 additions & 1 deletion lib/cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,27 @@ module.exports = function cast(schema, obj, options, context) {
if (!Array.isArray(val)) {
throw new CastError('Array', val, path);
}
for (let k = 0; k < val.length; ++k) {
for (let k = val.length - 1; k >= 0; k--) {
if (val[k] == null || typeof val[k] !== 'object') {
throw new CastError('Object', val[k], path + '.' + k);
}
const beforeCastKeysLength = Object.keys(val[k]).length;
const discriminatorValue = val[k][schema.options.discriminatorKey];
if (discriminatorValue == null) {
val[k] = cast(schema, val[k], options, context);
} else {
const discriminatorSchema = getSchemaDiscriminatorByValue(context.schema, discriminatorValue);
val[k] = cast(discriminatorSchema ? discriminatorSchema : schema, val[k], options, context);
}

if (Object.keys(val[k]).length === 0 && beforeCastKeysLength !== 0) {
val.splice(k, 1);
}
}

// delete empty: {$or: []} -> {}
if (val.length === 0) {
delete obj[path];
}
} else if (path === '$where') {
type = typeof val;
Expand Down
20 changes: 20 additions & 0 deletions test/docs/cast.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,26 @@ describe('Cast Tutorial', function() {
// acquit:ignore:end
});

it('strictQuery removes casted empty objects', async function() {
mongoose.deleteModel('Character');
const schema = new mongoose.Schema({ name: String, age: Number }, {
strictQuery: true
});
Character = mongoose.model('Character', schema);

const query = Character.findOne({
$or: [{ notInSchema: { $lt: 'not a number' } }],
$and: [{ name: 'abc' }, { age: { $gt: 18 } }, { notInSchema: { $lt: 'not a number' } }],
$nor: [{}] // should be kept
});

await query.exec();
query.getFilter(); // Empty object `{}`, Mongoose removes `notInSchema`
// acquit:ignore:start
assert.deepEqual(query.getFilter(), { $and: [{ name: 'abc' }, { age: { $gt: 18 } }], $nor: [{}] });
// acquit:ignore:end
});

it('implicit in', async function() {
// Normally wouldn't find anything because `name` is a string, but
// Mongoose automatically inserts `$in`
Expand Down

0 comments on commit 75e1dd8

Please sign in to comment.