如果通过Mongoose在Mongodb中的另一个文档中存在引用,那么防止文档被删除的更好方法是什么?

时间:2016-10-13 07:24:16

标签: node.js mongodb express mongoose mongodb-query

我正在使用以下堆栈创建一个webapp:

  • 节点
  • 快速
  • MongoDB的
  • 猫鼬

我已将应用程序构建为MVC结构。

有Customer,OrderReceived和OrderSent模式。 OrderReceived和OrderSent模式引用Customer模式。 Abridge架构结构如下:

客户

<script type="text/javascript">

    function C(t, textBoxId) {
        $("#" + textBoxId).prop("disabled", !$(t).prop("checked"));
    }
</script>

<form:checkbox value="regular" id="chkReg" onclick="C(this, 'txtRegPrc')"/>

OrderReceived

const mongoose = require('mongoose');

const customerSchema = mongoose.Schema({
  companyName: String,
  firstName: { type: String, required: true},
  lastName: { type: String, required: true}
});

module.exports = mongoose.model('Customer', customerSchema);

OrderSent

const mongoose = require('mongoose');

const orderReceivedSchema = mongoose.Schema({
  receivedDate: { type: Date, required: true},
  customer: {type: mongoose.Schema.Types.ObjectId, ref: 'Customer', required: true}
});

module.exports = mongoose.model('OrderReceived', orderReceivedSchema);

当要求客户文档删除时,我想检查OrderReceived或OrderSent文档是否引用了该文档。如果存在,我想阻止删除客户文档。

我想出的解决方案是在客户的控制器中进行检查,如下所示:

CustomerController#destroy会处理删除请求:

const mongoose = require('mongoose');

const orderSentSchema = mongoose.Schema({
  sentDate: { type: Date, required: true},
  customer: {type: mongoose.Schema.Types.ObjectId, ref: 'Customer', required: true}
});

module.exports = mongoose.model('OrderSent', orderSentSchema);

有更好的方法吗?我还有其他型号也取决于客户文档,这个代码只会变得更加混乱。 请帮忙。

2 个答案:

答案 0 :(得分:1)

当您创建 OrderReceivedOrderSent 时,也将其引用保存在 Customer 中。 因此,在删除它之前,您可以通过这种方式简单地检查它们是否为空。 您的客户架构将类似于:

const customerSchema = mongoose.Schema({
    companyName: String,
    firstName: { type: String, required: true},
    lastName: { type: String, required: true},
    ordersSent: [{type: mongoose.Schema.Types.ObjectId, ref: 'OrderSent'}],
    ordersReceived: [{type: mongoose.Schema.Types.ObjectId, ref: 'OrderReceived'}],
});

并且您的删除函数应该包含以下内容:

Customer.findById(req.params.id)
    .then(customer => {
        if(customer.ordersSent.length== 0&& customer.ordersReceived.length== 0)
            return true
        //if there was more than 0
        return false
    }).then(result => {
        if(result)
            return Customer.findByIdAndRemove(req.params.id)
        res.status(409).json({message: 'There are orders received or sent using the Customer. Customer could not be deleted.'})
    }).then(customerDataJustInCase =>{
        res.status(200).json({message: 'Customer deleted.'})
    }).catch(err => {
        //your error handler
    })

或者你可以通过 try-catch 使用它。

答案 1 :(得分:0)

您可以使用 Promise.all 方法一次执行所有数据库查询,如下所示:

Promise.all([
  OrderReceived.count({customer: req.params.id}),
  OrderSent.count({'customer.customer': req.params.id})
])
  .then(([orderReceivedCount, orderSendCount]) => {
    if (orderReceivedCount < 1 && orderSendCount<1) { 
      ...delete doc 
    }
   }).catch(error => ...handleError)