Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Mongoose version
8.6.0
Node.js version
20.15.1
MongoDB server version
7
Typescript version (if applicable)
5.5.4
Description
Hi Mongoose team,
In version 8.6.0, the type definition for the filter parameter in updateMany was changed from FilterQuery to RootFilterQuery. This change restricts the use of certain MongoDB operators (such as $pull) that were allowed in 8.5.5.
This change causes TypeScript errors in existing codebases that rely on the old type definition, making it a breaking change. According to Semantic Versioning, this should have warranted a major version bump rather than a minor version change.
I think this change is a breaking change for existing codebases that use MongoDB operators in the filter parameter of updateMany and suggest that it may require a major version bump according to SemVer principles.
This is my prod code snippet, which works with version 8.5.5:
await GuardianModel.updateMany(
{ $pull: { wards: { $in: [userId] } } },
{ session },
);
with version 8.6.0, I need to add something to replace the filter to keep Typescript happy:
await GuardianModel.updateMany(
{},
// or undefined
// or { _id: { $exists: true } }
{ $pull: { wards: { $in: [userId] } } },
{ session },
);
This workaround does feel like a hack and is not intuitive, especially when your goal is to search all documents or apply a filter based on nested values.
Suggested Actions:
-
Revert the type change or consider bumping to a new major version.
-
Clearly document this change in the release notes to warn users.
Steps to Reproduce
- Initialize a new Node.js project with TypeScript.
- Install Mongoose version 8.5.5 first to demonstrate the working scenario, and then 8.6.0 to show the issue.
- Create a TypeScript file (index.ts) and define a simple Mongoose schema.
import mongoose, { Schema, Document } from 'mongoose';
// Define a simple Guardian schema
interface Guardian extends Document {
wards: Schema.Types.ObjectId[];
}
const GuardianSchema = new Schema<Guardian>({
wards: { type: [Schema.Types.ObjectId] }
});
const GuardianModel = mongoose.model<Guardian>('Guardian', GuardianSchema);
// Sample function that demonstrates the issue
async function testUpdateMany(userId: string) {
// This should work in version 8.5.5 but throws an error in 8.6.0
await GuardianModel.updateMany(
{ $pull: { wards: { $in: [userId] } } }, // Filter with $pull operator
{},
{}
);
}
- Compile and Run the Example with Version 8.5.5
- Upgrade to Mongoose Version 8.6.0
- Run TypeScript compilation and observe the TypeScript error: Object literal may only specify known properties, and '$pull' does not exist in type 'RootFilterQuery'.
Expected Behavior
The TypeScript code should compile without errors as it did in version 8.5.5, allowing MongoDB update operators like $pull in the filter parameter of updateMany.
Actual Behavior: The TypeScript compiler throws an error in version 8.6.0 due to the stricter type definition RootFilterQuery.