首页 > 解决方案 > Mongodb 在使用动态键的嵌套文档中添加两个值的问题

问题描述

我希望为我的每个子文档添加 currentAsset.total 和 longTermAsset.total,并带有一个新字段的动态键。我当前的 mongodb 版本是 4.0.12

我的源文件如下:

{
   "_id":"5f44bc4c36ac3e2c8c6db4bd",
   "counter":"Apple",
   "balancesheet":{
      "0":{
         "currentAsset":{
            "total":123.12
         },
         "longTermAsset":{
            "total":10.16
         }
      },
      "1":{
         "currentAsset":{
            "total":10.23
         },
         "longTermAsset":{
            "total":36.28
         }
      }
   }
}

我想得到的结果文件是:

{
    "_id": "5f44bc4c36ac3e2c8c6db4bd",
    "counter": "Apple",
    "balancesheet": {
        "0": {
            "currentAsset": {
                "total": 123.12
            },
            "longTermAsset": {
                "total": 10.16
            },
            "totalAsset": 133.28
        },
        "1": {
            "currentAsset": {
                "total": 10.23
            },
            "longTermAsset": {
                "total": 36.28
            },
            "totalAsset": 46.51
        }
    }
}

我尝试了一些聚合但失败了,因为它给了我“errmsg”:“$add 只支持数字或日期类型,不支持数组”

db.balancesheets.aggregate([
    {
        $match: { counter: "Apple" }
    },
    {
        $project: {
            bs: { $objectToArray: "$balancesheet" }
        }
    },
    {
        $addFields: {
            totalAsset: {
                $add: ["$bs.k.currentAsset.total", "$bs.k.longTermAsset.total"]
            }
        }
    }
])

正如我所指的那样,版本似乎需要为 4.2 及更高版本。反正有没有可以在我现有的 4.0.12 版本上做到这一点? MongoDB 聚合:通过动态字段路径从嵌入式文档中添加字段

标签: mongodbaggregate

解决方案


没有版本问题,请进行一些修复,

  • 前 2 条管道看起来不错,
  • $unwind解构bs数组
  • $addFields更正了,您在访问字段总计时使用了 k 而不是 v
  • $group重建并再次准备对象到数组
  • $addFields使用将 bs 数组转换为对象$reduce
db.collection.aggregate([
  // $match ... pipeline
  // $project ... pipeline

  // unwind bs array
  { $unwind: "$bs" },
  {
    $addFields: {
      "bs.v.totalAsset": { $add: ["$bs.v.currentAsset.total", "$bs.v.longTermAsset.total"] }
    }
  },
  {
    $group: {
      _id: "$_id",
      bs: { $push: { $arrayToObject: [["$bs"]] } },
      counter: { $first: "$counter" },
    },
  }
  {
    $addFields: {
      bs: {
        $reduce: {
          input: "$bs",
          initialValue: {},
          in: { $mergeObjects: ["$$value", "$$this"] }
        }
      }
    }
  }
])

操场


推荐阅读