Mongodb 在动态键的情况下用于对象替换的聚合

Mongodb aggregation for object replacement in case of dynamic keys

假设我有以下集合 _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
}

Tip:

infocoin = iron + sliver + wood

barron1 + barron2 = black + yellow + red

  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 = iron + sliver + wood

barron1 + barron2 = black + yellow + red

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

这个答案其实和@yong-shun'is 一样,只是把所有东西合二为一"$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 上试用。