【问题标题】:How do I remove an array of referenced Objects when deleting the main document?删除主文档时如何删除引用的对象数组?
【发布时间】:2019-08-26 17:28:52
【问题描述】:

这是我的 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时,我也可以假设属于菜单的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');
      });
    });

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

【问题讨论】:

  • Product.remove({ _id: req.body.products }) 就足够了,但要确保它是 ids 数组

标签: node.js mongodb mongoose mongoose-populate


【解决方案1】:

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

阅读更多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 是您的模型的名称。

【讨论】:

    【解决方案2】:

    试试这个它对我有用。

    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');
      });
    });
    

    【讨论】:

      【解决方案3】:

      你可以使用下面的 mongoose 的 post schema 钩子

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-22
        • 1970-01-01
        • 1970-01-01
        • 2023-01-30
        相关资源
        最近更新 更多