mongoose-delete 默认不生效是因为仅启用逻辑标记而不自动过滤查询结果,需手动配置overridemethods或调用withdeleted方法,并注意aggregate等非标准操作需自行添加过滤条件。

为什么 mongoose-delete 默认不生效?
因为插件默认只启用「逻辑标记」,不自动过滤查询结果——你得手动调用 .find() 之外的方法,或显式开启全局过滤。常见现象是:删完还能查到文档,deletedAt 字段有值但 isDeleted 仍为 false。
实操建议:
- 初始化 schema 时必须传入
{ deleted: { type: Date, default: null } }或类似字段,否则插件无法挂载删除状态 - 调用
schema.plugin(require('mongoose-delete'), { overrideMethods: true })才能让.find().findOne()等自动过滤已删数据 - 如果用了
overrideMethods: 'all',注意.countDocuments()也会被覆盖(但.estimatedDocumentCount()不会)
如何查出「包括已删除」的数据?
软删除后,默认所有读操作都跳过已删文档。真要查全部,不能靠 .find({ isDeleted: false }) 这种写法——插件已重写了方法逻辑,该条件会被忽略。
实操建议:
- 用
.findWithDeleted()替代.find() - 用
.findOneWithDeleted()替代.findOne() - 恢复单条数据时,别用
.save(),直接调用.restore()方法(它会清空deletedAt并设isDeleted为false)
deletedAt 和 isDeleted 字段怎么选?
插件默认只加 deletedAt,但很多业务需要布尔标识快速判断。两者语义不同,影响索引和查询效率。
实操建议:
- 加
isDeleted: { type: Boolean, default: false }后,记得在 schema 上加index: true,否则按是否删除查询会慢 - 如果只用
deletedAt,可用{ deletedAt: { $ne: null } }查询已删数据,但无法利用稀疏索引优化 - 同时存两个字段时,插件会自动同步更新——删时设
isDeleted = true+deletedAt = new Date(),恢复时全清空
聚合查询(aggregate)里怎么过滤已删数据?
mongoose-delete 不拦截 .aggregate(),所有阶段都不自动加 $match。这是最容易漏掉的坑:列表页用 find 没问题,但后台导出用 aggregate 就可能把已删数据一起吐出去。
实操建议:
- 在 pipeline 开头手动加
{ $match: { deletedAt: { $eq: null } } }(假设你用的是deletedAt字段) - 如果 schema 启用了
isDeleted,就用{ $match: { isDeleted: false } } - 别依赖
options.overrideMethods对aggregate生效——它根本不处理这个方法










