mongodb 具有多个子组的聚合

mongodb aggregation with multiple sub groups

我有一个 collection 文件看起来类似于:

[
    {
        "_id": ObjectId("..."),
        "date": ISODate("..."),
        "type": "TypeA",
        "color": "ColorA",
        "soldFor": 12.15
    },
    {
        "_id": ObjectId("..."),
        "date": ISODate("..."),
        "type": "TypeA",
        "color": "ColorB",
        "soldFor": 13.15
    },
    {
        "_id": ObjectId("..."),
        "date": ISODate("..."),
        "type": "TypeB",
        "color": "ColorA",
        "soldFor": 12.15
    },
    {
        "_id": ObjectId("..."),
        "date": ISODate("..."),
        "type": "TypeB",
        "color": "ColorB",
        "soldFor": 12.15
    }
]

我知道这不是存储此类信息的好方法,但不幸的是我对此没有影响。 我需要从 collection 中得到的是这样的:

[
    2017: {
        typeA: {
            colorA: {
                sum: 125.00
            },
            colorB: {
                sum: 110.00
            }            
        },
        typeB: {
            colorA: {
                sum: 125.000
            }
        }        
    },
    2016: {
        typeA: {
            colorB: {
                sum: 125.000
            }
        }
    }
]

目前我有两个小组赛阶段,每个阶段都按年份分组,但我不知道如何获得另外两个 sub-groups。建立总和会很不错,但我确信我可以弄清楚如何在一个小组中完成。

到目前为止我的管道是这样的:

[
    {
      $group: {
        _id: { type: '$type', color: '$color', year: { $year: '$date' } },
        docs: {
          $push: '$$ROOT'
        }
      }
    },
    {
      $group: {
        _id: { year: '$_id.year' },
        docs: {
          $push: '$$ROOT'
        }
      }
    }
]

结果如下:

[
    {
        "_id": {
            "year": 2006
        },
        "docs": {
            "_id": {
                "type": "typeA",
                "color": "colorA",
                "year": 2006
            },
            "docs": [
                {
                    ... root document
                }
            ]
        }
    },
    {
        "_id": {
            "year": 2016
        },
        "docs": [
            {
                "_id": {
                    "type": "typeA",
                    "color": "colorB",
                    "year": 2016
                },
                "docs": [
                    {
                        ... root document
                    }
                ]
            }
            ... more docs with three keys in id
        ]
    }
]

非常感谢您的帮助!

使用 MongoDB 3.4.4 及更新版本中的一组运算符,即 $addFields, $arrayToObject and $replaceRoot,您可以组成如下所示的管道以获取期望的结果:

[
    { "$group": {
        "_id": { 
            "year": { "$year": "$date" },
            "type": "$type",
            "color": "$color"
        },
        "count": { "$sum": "$soldFor" }
    } },
    { "$group": {
        "_id": {
            "year": "$_id.year",
            "type": "$_id.type"
        },
        "counts": {
            "$push": {
                "k": "$_id.color",
                "v": { "sum": "$count" }
            }
        }
    } },
    { "$addFields": {
        "counts": { "$arrayToObject": "$counts" }
    } },
    { "$group": {
        "_id": "$_id.year",
        "counts": {
            "$push": {
                "k": "$_id.type",
                "v": "$counts"
            }
        }
    } },
    { "$addFields": {
        "counts": { "$arrayToObject": "$counts" }
    } },
    { "$group": {
        "_id": null,
        "counts": {
            "$push": {
                "k": { "$substr": ["$_id", 0, -1 ]},
                "v": "$counts"
            }
        }
    } },
    { "$replaceRoot": { 
        "newRoot": { 
            "$mergeObjects": [ 
                { "$arrayToObject": "$counts" }, 
                "$$ROOT" 
             ] 
        } 
    } },
    { "$project": { "counts": 0 } }
]