如何在NestJS中使用Mongoose实现级联删除?
在Nest.js中实现学生删除时级联删除选课记录的方案
以下是两种可靠的实现方式,适配不同的删除调用场景:
方式一:文档实例级中间件(pre('remove'))
该方案针对文档实例的remove()方法生效,需确保服务层先查询到学生文档再执行删除。
步骤1:导入依赖
在Student Schema文件顶部,引入Enrollment模型及mongoose核心:
import { Enrollment } from './enrollment.schema'; // 替换为你的实际文件路径 import mongoose from 'mongoose';
步骤2:添加级联删除中间件
在StudentSchema定义完成后,追加以下中间件逻辑:
StudentSchema.pre('remove', async function(next) { // this 指向当前待删除的Student文档实例 await mongoose.model(Enrollment.name).deleteMany({ student: this._id }); next(); });
服务层调用示例
在学生服务类中,使用文档实例的remove()方法触发中间件:
// student.service.ts async deleteStudent(id: string) { const student = await this.studentModel.findById(id); if (!student) { throw new NotFoundException('学生不存在'); } await student.remove(); // 触发pre('remove')级联删除 return { message: '学生及关联选课记录已删除' }; }
方式二:模型级中间件(pre('deleteOne'))
如果习惯使用模型的deleteOne/findByIdAndDelete方法,可通过该方案覆盖文档实例和模型调用两种场景:
添加双场景中间件到StudentSchema
// 文档实例级deleteOne触发的中间件 StudentSchema.pre('deleteOne', { document: true, query: false }, async function(next) { await mongoose.model(Enrollment.name).deleteMany({ student: this._id }); next(); }); // 模型级deleteOne触发的中间件(如StudentModel.deleteOne({_id: id})) StudentSchema.pre('deleteOne', { document: false, query: true }, async function(next) { const query = this.getQuery(); await mongoose.model(Enrollment.name).deleteMany({ student: query._id }); next(); });
服务层调用示例
此时两种删除方式均可触发级联:
// 方式1:模型直接调用deleteOne async deleteStudent(id: string) { const result = await this.studentModel.deleteOne({ _id: id }); if (result.deletedCount === 0) { throw new NotFoundException('学生不存在'); } return { message: '学生及关联选课记录已删除' }; } // 方式2:文档实例调用deleteOne async deleteStudent(id: string) { const student = await this.studentModel.findById(id); if (!student) { throw new NotFoundException('学生不存在'); } await student.deleteOne(); return { message: '学生及关联选课记录已删除' }; }
关键注意事项
- 确保Enrollment模型已在Nest模块中正确注册,否则
mongoose.model(Enrollment.name)会抛出未找到模型的错误。 - 若业务需要数据强一致性,需将级联删除操作纳入Mongoose事务中。
- 区分文档中间件与查询中间件的作用范围,根据实际使用的删除方法选择对应中间件类型。
内容的提问来源于stack exchange,提问作者Zoodek
相关产品推荐
相关产品推荐

