【问题标题】:MongoDB Aggregation - Perform sum for the value in the objects with dynamic keysMongoDB 聚合 - 使用动态键对对象中的值执行求和
【发布时间】:2022-11-28 09:27:17
【问题描述】:

假设我有以下带有_idtraits 的集合。

[
    {
      _id: 1,
      traits: {
        Rarity: {
          infoin: 15,
        },
        Type: {
          iron: 3,
          sliver: 5,
          wood: 7,
        },
      },
    },
    {
      _id: 2,
      traits: {
        Cloth: {
          barron1: 11,
          barron2: 12,
        },
        Hair: {
          black: 6,
          yellow: 9,
          red: 8
        }
      },
    },
    ...
]

如您所见,traits 的键是动态的,子对象的键也是动态的。

这是我想要得到的结果:

[
    {
      _id: 1,
      traits: 15,
    },
    {
      _id: 2,
      traits: 23
    }
]

小费:

infocoin = 铁 + 银 + 木

barron1 + barron2 = 黑色 + 黄色 + 红色

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:
    1. $set - 通过$objectToArray将对象转换为数组来设置traitObjs数组字段。

    2. $set - 通过从traitObjs数组获取第一个文档的值来设置firstTraitValues字段,然后通过$objectToArray从对象转换为数组。

    3. $project - 修饰输出文档。通过将firstTraitValues数组转换为带有$reduce$sum所有v值的数字类型来设置traits字段。

      db.collection.aggregate([
        {
          $set: {
            traitObjs: {
              $objectToArray: "$traits"
            }
          }
        },
        {
          $set: {
            firstTraitValues: {
              $objectToArray: {
                $first: "$traitObjs.v"
              }
            }
          }
        },
        {
          $project: {
            traits: {
              $reduce: {
                input: "$firstTraitValues",
                initialValue: 0,
                in: {
                  $sum: [
                    "$$value",
                    "$$this.v"
                  ]
                }
              }
            }
          }
        }
      ])
      

      Sample Mongo Playground


      由于traits的第一个密钥文档和第二个密钥文档中的所有值都相同,

      infocoin = 铁 + 银 + 木

      barron1 + barron2 = 黑色 + 黄色 + 红色

      因此,上述方法只是总结了traits 的第一个关键文档中的所有值。

    【讨论】:

    • 感谢您的回答,它运作良好。但是我想问你,你的答案优化了吗……还有更好的答案吗?实际上我在这个收藏中有很多很多文件
    【解决方案2】:

    这个答案真的和@yong-shun 的answer 一样,但是它把所有的东西都合成了一个"$project"。我不知道它是否会更有效率。

    db.collection.aggregate([
      {
        "$project": {
          "traits": {
            "$reduce": {
              "input": {
                "$objectToArray": {
                  "$getField": {
                    "field": "v",
                    "input": { "$first": { "$objectToArray": "$traits" } }
                  }
                }
              },
              "initialValue": 0,
              "in": { "$sum": [ "$$value", "$$this.v" ] }
            }
          }
        }
      }
    ])
    

    试试mongoplayground.net

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-27
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多