MongoDB - 需要帮助才能进行一些聚合

时间:2018-02-19 02:13:17

标签: mongodb aggregate

我很难在MongoDB中进行聚合。

我需要跨越每个用户的一些信息,作为最终结果,我想要一个用户列表(每个用户只有一个对象),每个对象都有一些包含不同信息的列表。

1 - createdAtList数组必须从最旧日期到最新日期排序。 sumOfTotal表示当前位置total总结为之前的sumOfTotal(以下代码中的示例),而不仅仅是total's

的总和

2 - 必须按categotyList

订购category1, category2, category3 ...

3 - 必须按以下方式订购所需的最终结果:user1, user2, user3 ...

基本上我需要一些帮助才能做到以下几点:

//List of docs from my collection:
[
    {
        _id: "doc1",
        user: "user1",
        category: "category1",
        createdAt: "2018-01-01T00:00:00.000Z"
    },
    {
        _id: "doc2",
        user: "user1",
        category: "category2",
        createdAt: "2017-12-12T00:00:00.000Z",
    },
    {
        _id: "doc3",
        user: "user1",
        category: "category1",
        createdAt: "2017-12-12T00:00:00.000Z",
    },
    {
        _id: "doc4",
        user: "user1",
        category: "category2",
        createdAt: "2018-01-01T00:00:00.000Z"
    },
    {
        _id: "doc5",
        user: "user1",
        category: "category3",
        createdAt: "2017-11-11T00:00:00.000Z"
    }
]

//Desired result:
{
    user: "user1",
    createdAtList: [ //list ordered by createdAt
        {
            createdAt: "2017-11-11T00:00:00.000Z",
            total: 1,
            sumOfTotal: 0
        }
        {
            createdAt: "2017-12-12T00:00:00.000Z",
            total: 2,
            sumOfTotal: 3 //summed up with the previous
        }
        {
            createdAt: "2018-01-01T00:00:00.000Z",
            total: 2,
            sumOfTotal: 5 //summed up with the previous
        }
    ],
    categotyList: [ //list ordered by category
        {
            category: "category1",
            total: 2
        },
        {
            category: "category2",
            total: 2
        },
        {
            category: "category3",
            total: 1
        }
    ]
},
...

可以在同一个聚合中执行此操作吗?

1 个答案:

答案 0 :(得分:1)

我认为拥有createdAtList.sumOfTotal字段确实没有意义。我不认为数组中的字段应该依赖于元素的特定顺序。如果你想要一些字段包含createdAtList.total字段的总和,我认为应该只有一个字段(在数组之外)。话虽这么说,这是我提出的查询给你想要的结果(使用“users”作为集合的名称):

db.users.aggregate([
    {
        $group: {
            _id: {
                user: "$user",
                createdAt: "$createdAt"
            },
            total: { $sum: 1 },
            category: { $push: "$category" }
        }
    },
    {
        $project: {
            _id: 0,
            user: "$_id.user",
            createdAt: "$_id.createdAt",
            total: "$total",
            category: 1
        }
    },
    { $unwind: "$category" },
    {
        $group: {
            _id: {
                user: "$user",
                category: "$category"
            },
            catTotal: { $sum: 1 },
            createdAtList: {
                $push: {
                    createdAt: "$createdAt",
                    total: "$total"
                }
            }
        }
    },
    {
        $project: {
            _id: 0,
            user: "$_id.user",
            createdAtList: 1,
            category: "$_id.category",
            catTotal: 1
        }
    },
    { $unwind: "$createdAtList" },
    {
        $group: {
            _id: "$user",
            createdAtList: {
                $addToSet: "$createdAtList"
            },
            categoryList: {
                $addToSet: {
                    category: "$category",
                    total: "$catTotal"
                }
            }
        }
    },
    { $unwind: "$createdAtList" },
    { $sort: { "createdAtList.createdAt": 1 } },
    {
        $group: {
            _id: "$_id",
            createdAtList: {
                $push: "$createdAtList"
            },
            categoryList: {
                $first: "$categoryList"
            }
        }
    },
    { $unwind: "$categoryList" },
    { $sort: { "categoryList.category": 1 } },
    {
        $group: {
            _id: "$_id",
            createdAtList: {
                $first: "$createdAtList"
            },
            categoryList: {
                $push: "$categoryList"
            }
        }
    },
    {
        $project: {
        _id: 0,
        user: "$_id",
        createdAtList: 1,
        sumOfTotal: { $sum: "$createdAtList.total" },
        categoryList: 1
        }
    },
    { $sort: { user: 1 } },
]).pretty()