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

时间:2019-08-26 09:07:52

标签: node.js mongodb mongoose mongoose-populate

这是我的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');
      });
    });

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

3 个答案:

答案 0 :(得分:0)

试试这个对我有用。

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

答案 1 :(得分:0)

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

了解更多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}})
}

假设产品是您的型号名称。

答案 2 :(得分:0)

您可以如下使用猫鼬的后架构钩子

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