Mongoose和数据完整性

时间:2016-06-11 12:16:41

标签: node.js mongodb mongoose

如果我定义了以下模式,如何在更新和删除期间保持集合同步:

var RestaurantSchema = mongoose.Schema({
    name: {
        type: String,
        required: true,
    },
    menus: [{ 
        type: mongoose.Schema.Types.ObjectId, 
        ref: 'Menu' 
    }]
});

var MenuSchema = mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    restaurant: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Restaurant',
        required: true
    }
});

我通过以下方式创建了一家餐馆:

Restaurant.create(restaurant, callback);

我创建了一个菜单,并通过执行以下操作将其链接到餐厅:

Menu.create(menu, function(err, menu) {
    if (err) {
        callback(err, menu);
    }
    else {
        restaurantController.addMenu(menu.restaurant, menu._id,
            function(err, restaurant) {
                callback(err, menu);
            });
    }
});

第一个问题,是否有更好的方法向餐馆添加菜单?

第二个问题,当我删除菜单或删除餐馆时如何保持数据同步?

第三个问题,当我执行从参考字段中删除id的更新时,如何在集合中保持数据同步。例如,如果我这样做:

Restaurant.findOneAndUpdate({ _id: _id }, { $unset.menus }, options, callback);

这将清空餐厅文档上的菜单数组,但菜单文档仍然会引用餐厅。

1 个答案:

答案 0 :(得分:1)

IMO MenuRestaurant应具有单向关系。因此,Restaurant实体可以引用Menu(如果餐厅和菜单需要为1-1)或者菜单1-n(早餐,午餐,晚餐等等)的集合。

Menu无需引用Restaurant,因为这可能会导致循环引用问题。

此外,数据完整性可能会被搞砸。 例如,如果Restaurant-A引用了Menu-A,但Menu-A引用了Restaurant-B,该怎么办?

关于你的问题: 第一个问题,是否有更好的方法向餐馆添加菜单?

  1. 创建Menu,应该返回_id
  2. 将该引用添加到Restaurant myRestaurant.menuId = _id
  3. 更新餐厅。

    PS:您可以使用promises来平整您的结构。

  4. 第二个问题,当我删除菜单或删除餐馆时如何保持数据同步?

    您正在查看需要作为交易运行的2 db操作(删除菜单,从餐厅删除菜单参考)。了解如何进行多文档交易 https://docs.mongodb.com/manual/tutorial/perform-two-phase-commits/

    我的上述答案可能足以满足您的第三个问题。

    这将清空餐厅文档上的菜单数组,但菜单文档仍然会引用餐厅。

    如果您将架构重新连接为单向,则不必担心这一点。

    希望这有帮助。