简体   繁体   中英

How to aggregate over map keys across all the documents in mongodB collection?

I have data in the following format:

[{
"OrderId": "406-5309498-5972326",
"revenueHeader": {
"Principal": 982.14,
"Product Tax": 117.86,
"Total": 1100
}},
{
"OrderId": "506-5234568-5934567",
"revenueHeader": {
"Principal": 382.54,
"Product Tax": 34.46,
"Shipping charge": 30.5,
"Giftwrap charge": 27.5,
"Total": 234
}}]

How can I sum the revenueHeader map values for the keys across all the documents? Note: "Shipping charge" is not present in the first document but we still want the sum for this key across all the documents. Also, the keys can vary, there is no way to know the name of keys beforehand.

You have to use $objectToArray to transform revenueHeader in an array of {k,v} object.

You can then $unwind the array, and group by revenueHeader.k, summing revenueHeader.v . By this way, you never take care of the fields name or presence inside revenueHeader.

Here's the query :

db.collection.aggregate([
  {
    $project: {
      revenueHeader: {
        $objectToArray: "$revenueHeader"
      }
    }
  },
  {
    $unwind: "$revenueHeader"
  },
  {
    $group: {
      _id: "$revenueHeader.k",
      total: {
        $sum: "$revenueHeader.v"
      }
    }
  }
])

You can test it here

If you are not sure about how many fields are going to be there for which you want to get the sum of values across documents then you can go with the solution given by @matthPen.

But if you know all the possible fields present then you can use directly use the $group stage with key names. As I personally avoid using $unwind if number of documents is very large.

[ 
    { 
        $group: { 
            _id: null,
            "Principal": { $sum: "$revenueHeader.Principal" },
            "Product Tax": { $sum: "$revenueHeader.Product Tax" },
            "Shipping charge": { $sum: "$revenueHeader.Shipping charge" },
            "Giftwrap charge": { $sum: "$revenueHeader.Giftwrap charge" },
            "Total": { $sum: "$revenueHeader.Total" },
        } 
    } 
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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