删除主文档时如何删除引用对象数组?

How do I remove an array of referenced Objects when deleting the main document?

这是我的 MongoDB 架构:

const MenuSchema = new Schema({
  name: {
    type: String,
    require: true
  },
  category: {
    type: String,
    require: true
  },
  description: {
    type: String,
    require: true
  },
  image: {
    type: String,
  },
  caterer: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  },
  products: [{
    type: Schema.Types.ObjectId,
    ref: 'Product'
  }]
}, { timestamps: true })


const ProductSchema = new Schema({
  name: {
    type: String,
    require: true
  },
  category: {
    type: String,
    require: true
  },
  description: {
    type: String,
    require: true
  },
  image: {
    type: String,
  },
  price: {
    type: String
  }
}, { timestamps: true })

我想知道的是如何在删除主 "Menu" 文档的同时删除产品数组?当我删除 Menu 时,我也可以假设属于菜单的 products 应该被删除。

目前我是这样删除菜单的(并试图删除它的产品):

await Menu.findOneAndDelete({ _id: req.params.menu_id }, (err, response) => {
      if (err) {
        console.error(err);
      }
      Product.remove({ _id: { $in: req.body.products }}, (err, res) => {
        if (err) {
          console.error(err);
        }
        console.log('Deleted products');
      });
    });

但是,产品不会被删除。有什么建议吗?

试试这个对我有用。

await Menu.findOneAndDelete({ _id: req.params.menu_id }, (err, response) => {
  if (err) {
    console.error(err);
  }
  Product.remove({ _id: { $in: response.products }}, (err, res) => {
    if (err) {
      console.error(err);
    }
    console.log('Deleted products');
  });
});

Mongoose 在您的架构上提供了一个 pre 和 post 中间件。这意味着您可以在对当前架构执行操作之前或之后删除所有引用的文档。

阅读更多here

这是一个示例,在您的架构中添加:

const MenuSchema = new Schema({
  name: {
    type: String,
    require: true
  },
  category: {
    type: String,
    require: true
  },
  description: {
    type: String,
    require: true
  },
  image: {
    type: String,
  },
  caterer: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  },
  products: [{
    type: Schema.Types.ObjectId,
    ref: 'Product'
  }]
}, { timestamps: true })


const ProductSchema = new Schema({
  name: {
    type: String,
    require: true
  },
  category: {
    type: String,
    require: true
  },
  description: {
    type: String,
    require: true
  },
  image: {
    type: String,
  },
  price: {
    type: String
  }
}, { timestamps: true })


MenuSchema.post('remove', removeProducts);

function removeProducts(doc) {
   Products.remove({_id: { $in: doc.products}})
}

假设 Products 是您的型号名称。

您可以使用 post mongoose 的模式挂钩,如下所示

schema.post('remove', function(doc) {
  console.log('%s has been removed', doc._id);
});

Mongoose Post Hook

但最好的方法是使用事务对数据库执行多个操作,如下所示。

let session = null;
db.startSession()
.then((_session) =>{
    session = _session;
    session.startTransaction();
    return Menu.deleteOne({ _id: req.params.menu_id });
})
.then(()=> Product.deleteMany({ _id: { $in: req.body.products }}))
.then(()=>{
    session.commitTransaction();
})
.catch((err)=>{
    session.abortTransaction()
    return handleError(err);
})

Mongoose Transactions