【问题标题】:How to loop through mongodb subdocument array find the matching elements and update the element fields with new values at once如何遍历mongodb子文档数组找到匹配的元素并立即用新值更新元素字段
【发布时间】:2020-12-05 01:04:36
【问题描述】:

例如,如果采购订单有这样的行项目:

来自客户端的用户将要更新的订单项发送到一个名为 lineItemsToUpdate 的数组中,格式如下:

[
{       unitCost: 342,
        totalQuantity: 13,
        acceptedQuantity: 6,
        rejectedQuantity: 18,
        title: 'Unbranded Concrete Pizza',
        description: 'Soft',
        variant: 5f2d5eb0195026e6dd549ef0 },
      { unitCost: 189,
        totalQuantity: 95,
        acceptedQuantity: 49,
        rejectedQuantity: 16,
        title: 'Handcrafted Rubber Cheese',
        description: 'Assurance',
        variant: 5f2d5eaf195026e6dd549b7d },
      { unitCost: 267,
        totalQuantity: 18,
        acceptedQuantity: 93,
        rejectedQuantity: 11,
        title: 'Incredible Soft Car',
        description: 'solution-oriented',
        variant: 5f2d5eb0195026e6dd549d3d },
]

在 lineItemsToUpdate 数组中,每个元素的值可能已被客户端更改,如果我以用户的格式描述它,我想通过子文档中的变量字段更新所有匹配元素故事:

根据 lineItemsToUpdate 数组更新所有 lineItems“字段”,其中 lineItemsToUpdate.[elem].variant === linitem.[elem].variant 使用 $set,如果可能,使用 $each 和 arrayFilters 运算符

我通过 mongodb 文档阅读了一些示例,如下所示:

db.students2.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
   }
)

但这里{ $set: { "grades.$[elem].mean" : 100 } } 的问题是 100 值是恒定的,我希望这部分是动态的,正如我在上面描述的那样。

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    以下是你必须使用的 JS 函数。

    function(c1,arr2){
        var arr1 = c1.next().lineItems;
        for(i=0;i<arr1.length;i++){
            for(j=0;j<arr2.length;j++){
                if(arr1[i].variant===arr2[j].variant){
                    db.purchaseOrder.update(
                    { },
                    { $set: { "lineItems.$[elem].unitCost" : arr2[j].unitCost,"lineItems.$[elem].totalQuantity" : arr2[j].totalQuantity } .....},
                    { multi: true,
                      arrayFilters: [ { "elem.variant": { $eq: arr2[j].variant } } ]
                    }
                    )
                }
            }
        }
    }
    

    说明

    1. 我们必须传递 2 个参数:i) Mongo 光标和 ii) 一个数组。 光标是要更新的集合。对于你的情况,它是 采购订单。这里的数组是 lineItemsToUpdate 数组。

    2. 接下来我们用 2 个 for 循环来匹配光标和光标之间的 variant 字段 数组。

    3. 如果匹配,我们使用 update 更新采购订单 命令和 $set 运算符。

    执行

    1. 转到您的 Mongo Shell。确保当前数据库有购买 订单收集。

    2. 定义modifyItems函数如下。

      var modifyItems=function(c1,arr2){  
          var arr1 = c1.next().lineItems;  
          for(i=0;i<arr1.length;i++){  
              for(j=0;j<arr2.length;j++){  
                  if(arr1[i].variant===arr2[j].variant){  
                      db.purchaseOrder.update(  
                      { },  
                      { $set: { "lineItems.$[elem].unitCost" :     arr2[j].unitCost,"lineItems.$[elem].totalQuantity" : arr2[j].totalQuantity }...    },  
                      { multi: true,  
                        arrayFilters: [ { "elem.variant": { $eq:   arr2[j].variant } } ]  
                      }  
                      )  
                  }  
              }  
          }  
      }  
      
    3. 定义一个变量arr,其中包含lineItemsToUpdate

      var arr=[  
            { unitCost: 342,  
              totalQuantity: 13,  
              acceptedQuantity: 6,  
              rejectedQuantity: 18,  
              title: 'Unbranded Concrete Pizza',  
              description: 'Soft',  
              variant: 5f2d5eb0195026e6dd549ef0 },  
            { unitCost: 189,  
              totalQuantity: 95,  
              acceptedQuantity: 49,  
              rejectedQuantity: 16,  
              title: 'Handcrafted Rubber Cheese',  
              description: 'Assurance',  
              variant: 5f2d5eaf195026e6dd549b7d },  
            { unitCost: 267,  
              totalQuantity: 18,  
              acceptedQuantity: 93,  
              rejectedQuantity: 11,  
              title: 'Incredible Soft Car',  
              description: 'solution-oriented',  
              variant: 5f2d5eb0195026e6dd549d3d }  
      ]  
      
    4. 现在执行JS函数。

      modifyItems(db.purchaseOrder.find({},{"lineItems":1,"_id":0}),arr);  
      

    如果没有错误,您的采购订单行项目现在将使用数组值一次性更新。

    【讨论】:

    • 我可以很容易地通过批量写入来做到这一点。我想要一个高效且现代的解决方案,如果有 100 个订单项,您的解决方案将建立 100 个 mongo 连接,为什么我不应该使用批量写入而不是这个,我在问题标题中的“once”字词中也提到过。
    • 100 个 mongo 连接?它是单连接和 100 db 请求。考虑到您想使用动态值进行更新(正如您在问题中提到的,更新查询),我认为批量写入无法轻松完成。我的解决方案也由您的用户故事指定。
    猜你喜欢
    • 2019-06-21
    • 2015-11-04
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多