繁体   English   中英

MongoDB 更新(聚合管道)使用来自嵌套嵌套 Arrays 的值

[英]MongoDB Update (Aggregation Pipeline) using values from nested nested Arrays

我正在尝试根据嵌套的嵌套数组中的值更新我的文档中的字段(totalPrice)(addOns > 从 arrays 的 x 个数中获取匹配数组 > 在匹配数组中获取 int [总是在 pos 2] )。

这是一个包含 2 个 arrays 嵌套在 addOns 中的文档示例:

{
   "_id": ObjectID('.....'),
   "addOns": [
                ["appleId", "Apples", 2],
                ["bananaID", "Bananas", 1]
             ],
   "totalPrice": 5.7
}

假设香蕉的价格上涨了 20 美分,所以我需要查找其插件中包含香蕉的所有文档,然后根据购买的香蕉数量增加这些文档的 totalPrice。 我计划使用一个聚合管道来使用 updateMany() 查询,它应该大致类似于下面的示例。 这??? 应该是购买的香蕉数量,但我不确定如何通过 go 检索该值。 到目前为止,我一直在考虑使用 $unwind、$filter 和 $arrayElemAt,但不确定如何将它们一起使用。 将不胜感激任何帮助!

db.collection('orders').updateMany(
     { $elemMatch: { $elemMatch: { $in: ['bananaID'] } } },
     [
          { $set: {'totalPrice': { $add: ['$totalPrice', { $multiply: [{$toDecimal: '0.2'}, ???] } ] } } }
     ]

我不确定我的 mongo 版本是什么,但我知道我可以使用聚合管道,因为我还有其他 updateMany() 调用也使用管道没有任何问题,所以它应该是(版本> = 4.2) .

**编辑:为???想到这一点,随着文档的更新,过滤步骤似乎有点工作,但值是 null 而不是更新后的价格。 不知道为什么

  1. 过滤 '$addOns' 数组以返回匹配的嵌套数组。
  2. 对于条件,使用 $eq 检查 [0] ('$$this.0') 处的元素是否与字符串 'bananaID' 匹配,如果它确实返回此嵌套数组。
  3. 使用 $arrayElemAt 和 position [0] 获取从步骤 1 返回的数组。
  4. 在第 3 步中的数组上再次使用 $arrayElemAt,位置为 [2],因为它是数量元素的索引
{ $arrayElemAt: [{ $arrayElemAt: [ { $filter: { input: "$addOns", as:'this', cond: { $eq: ['$$this.0', 'bananaID'] } } } , 0 ] }, 2 ] }

设法自己解决了这个问题 - 虽然只有在你不介意问题评论中乔所说的 updateMany() 风险的情况下才使用它。 它与我最初在 ** Edit中共享的内容非常相似,只是您不能使用$$this.0访问数组中的元素。

把这个插入到哪里??? 是并且它会起作用,在这个代码块下面是解释:

{ $arrayElemAt: [{ $arrayElemAt: [ { $filter: { input: "$addOns", as:'this', cond: { $eq: [{$arrayElemAt:['$$this', 0]}, 'bananaID'] } } } , 0 ] }, 2 ] }
  1. 我们的数组如下所示: [["appleId", "Apples", 2], ["bananaID", "Bananas", 1]]
  2. 使用 $filter 来返回我们数组的一个子集,它只包含与我们的条件匹配的元素——在这种情况下,我们想要香蕉的数组。 $$this代表输入中的每个元素,我们检查$$this的第一个元素是否匹配'bananaID'。
{ $filter: { input: "$addOns", as:'this', cond: { $eq: [{$arrayElemAt:['$$this', 0]}, 'bananaID'] } } }

// how the result from $filter should look like
// [["bananaID", "Bananas", 1]]
  1. 因为嵌套的香蕉数组总是第一个元素,所以我们在第 2 步的结果中使用 $arrayElemAt 来检索 position 0 处的元素。
// How it looks like after step 3: ["bananaID", "Bananas", 1]
  1. 最后一步是再次使用 $arrayElemAt,除了这次我们要检索 position 2 处的元素(购买的香蕉数量)
  2. 这是评估步骤 1-4 后最终 updateMany() 查询的样子。
db.collection('orders').updateMany(
     { $elemMatch: { $elemMatch: { $in: ['bananaID'] } } },
     [
          { $set: {'totalPrice': { $add: ['$totalPrice', { $multiply: [{$toDecimal: '0.2'}, 1] } ] } } }
     ], *callback function code*)

// notice how the ??? is now replaced by the quantity of bananas which is 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM