I would like to delete all 'Shifts' related to 'Event', this code throws this error in VSCode:
No overload matches this call. The last overload gave the following error. Argument of type '"remove"' is not assignable to parameter of type 'RegExp | "insertMany"'.
And this on next() function:
This expression is not callable.
Type 'NativeError' has no call signatures.
const eventSchema = new Schema<EventInterface>({
userId: {
type: String,
required: true
},
studio: {
type: Schema.Types.ObjectId,
ref: 'Studio'
},
shifts: [{
type: Schema.Types.ObjectId,
ref: 'Shift'
}],
date: {
type: Date,
required: true
},
class: {
type: Schema.Types.ObjectId,
ref: 'Class',
required: true
},
isActive: {
type: Boolean,
default: true
}
}, {
timestamps: true,
versionKey: false
});
// Middleware to handle post-remove event
eventSchema.post<EventInterface>('remove', { document: true }, async function (next) {
const event = this;
const Shift = model('Shift');
try {
// Delete all related Shift documents
await Shift.deleteMany({ _id: { $in: event.shifts } });
} catch (error) {
next(error);
}
});
From this PR:
because for 7.0 the
.remove()
function was just renamed.deleteOne()
And this issue:
remove()
was deprecated in a previous version, and removed in Mongoose 7. So this is expected.
They should update the documentation.
The solution is to use the deleteOne
document middleware.
E.g.
import mongoose from 'mongoose';
import util from 'util';
import { config } from '../../config';
mongoose.set('debug', true);
console.log(mongoose.version);
interface EventInterface {
userId: string;
shifts: any[];
}
const shiftSchema = new mongoose.Schema();
const Shift = mongoose.model('Shift', shiftSchema);
const eventSchema = new mongoose.Schema<EventInterface>({
userId: String,
shifts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Shift',
},
],
});
eventSchema.post<EventInterface>('deleteOne', { document: true, query: false }, async function (doc, next) {
const event = this;
const Shift = mongoose.model('Shift');
console.log('doc:', doc, doc instanceof Event);
console.log('this:', this, this === doc);
try {
await Shift.deleteMany({ _id: { $in: event.shifts } });
} catch (error) {
next(error);
}
});
const Event = mongoose.model('Event', eventSchema);
(async function main() {
try {
await mongoose.connect(config.MONGODB_URI);
// seed
const [s1, s2] = await Shift.create([{}, {}]);
const [e] = await Event.create([{ userId: '1', shifts: [s1, s2] }]);
await e?.deleteOne();
} catch (error) {
console.error(error);
} finally {
await mongoose.connection.close();
}
})();
Logs:
7.3.2
Mongoose: shifts.insertOne({ _id: ObjectId("64b0d22b22fff59262045d23"), __v: 0 }, {})
Mongoose: shifts.insertOne({ _id: ObjectId("64b0d22b22fff59262045d24"), __v: 0 }, {})
Mongoose: events.insertOne({ userId: '1', shifts: [ ObjectId("64b0d22b22fff59262045d23"), ObjectId("64b0d22b22fff59262045d24") ], _id: ObjectId("64b0d22b22fff59262045d27"), __v: 0}, {})
Mongoose: events.deleteOne({ _id: ObjectId("64b0d22b22fff59262045d27") }, { session: null })
doc: {
userId: '1',
shifts: [
{ _id: new ObjectId("64b0d22b22fff59262045d23"), __v: 0 },
{ _id: new ObjectId("64b0d22b22fff59262045d24"), __v: 0 }
],
_id: new ObjectId("64b0d22b22fff59262045d27"),
__v: 0
} true
this: {
userId: '1',
shifts: [
{ _id: new ObjectId("64b0d22b22fff59262045d23"), __v: 0 },
{ _id: new ObjectId("64b0d22b22fff59262045d24"), __v: 0 }
],
_id: new ObjectId("64b0d22b22fff59262045d27"),
__v: 0
} true
Mongoose: shifts.deleteMany({ _id: { '$in': [ ObjectId("64b0d22b22fff59262045d23"), ObjectId("64b0d22b22fff59262045d24") ] }}, {})
As you can see, when you call the event.deleteOne()
method, it will trigger the post hook of the deleteOne
middleware.