首页 > 解决方案 > Mongoose:使用钩子/中间件删除引用的对象(有很多)

问题描述

在使用 Mongoose 的 nodejs 应用程序中,我有很多关系:App 有很多 AppClients。

楷模:

const mongoose = require('mongoose')

const appSchema = new mongoose.Schema({
  name: String,
  appClients : [{ type: mongoose.Schema.Types.ObjectId, ref: 'AppClient' }]
})

const App = mongoose.model('App', appSchema)

module.exports = App

const appClientSchema = new mongoose.Schema({
  access_key: String,
  secret_key: String
})

const AppClient = mongoose.model('AppClient', appClientSchema)

问题是我想在删除 App 文档时删除所有与 App 文档相关的 AppClients 文档。我目前的代码是:

exports.delete = async function(req, res, next) {

  const app = await App.findOne({ _id: req.params['id']}).exec()
  const listToDelete = [...app.appClients]

  await App.deleteOne({ _id: req.params['id']}).exec()
  await AppClient.remove({_id: {$in: listToDelete}}).exec()

  res.redirect('/apps')
}

这可行,但我想知道如何使用钩子。我已经查看了中间件,但我无法使其与 pre('remove') 一起使用,它永远不会被调用。我正在使用这样的东西:

appSchema.pre('remove', (next) => {
  console.log('pre remove') //never called
})

标签: javascriptnode.jsmongodbmongoosemongoose-schema

解决方案


remove是在模式级别(如您的示例中)指定的中间件,但它在文档级别上运行。因此,触发此事件的唯一方法是获取文档然后remove()在其上执行

const app = await App.findOne({ _id: req.params['id']}).exec();
await app.remove(); //prints 'pre remove'

Mongoose 文档中有一段关于此的内容:

注意:remove() 没有查询挂钩,仅适用于文档。如果您设置了一个“删除”挂钩,它将在您调用 myDoc.remove() 时触发,而不是在您调用 MyModel.remove() 时触发。注意: create() 函数会触发 save() 钩子。


推荐阅读