MongoDB - как слить поле документов dict? - PullRequest
3 голосов
/ 12 марта 2020

Например, у меня есть коллекция, которая выглядит следующим образом:

[{
    "_id": xxxx,
    "data": {
        "1": 10,
        "2": 30,
    }
},
{
    "_id": yyyy,
    "data": {
        "2": 10,
        "3": 30,
    }
}]

И я хочу суммировать data по ключу:

{
    "1": 10,
    "2": 40,
    "3": 30,
}

Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 12 марта 2020

Вы можете попробовать запрос ниже:

db.collection.aggregate([
    /** Convert data object into array of objects [{k:...,v:...}] */
    {
      $project: {
        data: {
          $objectToArray: "$data"
        }
      }
    },
    /** Unwind data array */
    {
      $unwind: "$data"
    },
    /** group on 'k' field of data field in each doc & sum values & push to 'v' field */
    {
      $group: {
        _id: "$data.k",
        v: {
          $sum: "$data.v"
        }
      }
    },
    /** Transform _id object as 'k' & v to 'v' of an object of array ([{k:...,v:...}]) &
     *  make an object of field named data */
    {
      $project: {
        _id: 0,
        data: {
          $arrayToObject: [
            [
              {
                k: "$_id",
                v: "$v"
              }
            ]
          ]
        }
      }
    },
    /** make data as new root to each doc */
    {
      $replaceRoot: {
        newRoot: "$data"
      }
    }
  ])

Тест: MongoDB-Playground

0 голосов
/ 12 марта 2020

Попробуйте это:

db.collection.aggregate([
  {
    $addFields: {
      data: {
        $objectToArray: "$data"
      }
    }
  },
  {
    $unwind: "$data"
  },
  {
    $group: {
      _id: "$data.k",
      data: {
        $sum: "$data.v"
      }
    }
  },
  {
    $group: {
      _id: null,
      data: {
        $push: {
          k: "$_id",
          v: "$data"
        }
      }
    }
  },
  {
    $addFields: {
      data: {
        $arrayToObject: "$data"
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: "$data"
    }
  }
])

MongoPlayground

...