以原子方式使用猫鼬更新复杂的嵌套对象

问题描述

我需要对数据库中多个父文档中的多个嵌套文档进行原子更新;场景如下:

模型看起来像这样(为了稀疏,我会保持简短):

const productvariantSchema = new mongoose.Schema({
    ...
    quantity: { type: Number,default: 0 }
});

const productSchema = new mongoose.Schema({
    ...
    variants: [productvariantSchema]
});

因此,我的产品包含包含库存的变体,下订单时我必须减少订购的变体的库存,也就是说,如果有人订购同一产品的多个变体或多个产品并且需要相应地减去每个库存(数量)的一个或多个变体。我通常会使用 for 循环(在内存中)执行此操作,但在这种情况下,该操作确实需要是原子的,因为如果产品的发货到达,管理员可以编辑库存。 有人能指出我正确的方向吗?

解决方法

好的,我想这就是我正在寻找的解决方案;查看文档我得出的结论是,在这种情况下需要进行交易。 Here is the documentation

总而言之,在我的情况下,我首先需要获取所有购物车项目并查看是否有一个产品具有多个变体,如果有,我需要相应地格式化该数据,以便稍后构建我的查询对象。这看起来像这样(为了稀疏再次缩短):

  1. 发布到 api 的购物车商品
     [{
            "productId": "ID here",...
            "variant": {
                "variantId": "ID here",...
                "variantStock": 160
            },"qty": 1
        },{
            "productId": "same ID",... ]
  1. 关联产品更新的数据
const uniqueProductIds = [...new Set(cartItems.map((item) => item.productId))];
const stockUpdateData = uniqueProductIds.map((id) => ({ productId: id,variants: cartItems.filter((item) => item.productId === id).map((item) => ({ variantId: item.variant.variantId,qty: item.qty,variantStock: item.variant.variantStock }))})); 

到目前为止,一切都很好。我拥有让这个工作所需的一切。在我的特定情况下,我首先更改数据库中的内容,然后向客户收费,因此如果数据库中出现任何问题,我只是不收费并通知用户错误等。这就是上述文档中交易的来源。由于我需要首先创建订单,然后相应地创建所有库存,因此我可以确定这将遵循 ACID 原则的唯一方法是使用交易。

所以我只是创建一个会话对象,调用 withTransaction() 方法并创建订单并从购物车相关数据更新所有产品变体库存。如果一切顺利,我只需向客户收费,并通过简单的更新将付款 ID 添加到订单中。

经过测试,它似乎按预期工作,但如果有人有更好或更简单的想法,我很乐意听到它。此外,非常欢迎任何建设性 批评