将值从MongoDB聚合的一部分传递到另一部分以对结果进行排序

时间:2017-11-22 11:36:12

标签: mongodb sorting aggregation

我遇到了一些MongoDB聚合问题,我正在尝试构建。我想得到一张表,其中包含我在一周内玩一些游戏的统计数据。我需要将它放入表中,按行中的游戏和列中的星期几来排序。单元格将包含一天中每个游戏玩量的百分比(意味着100%是在具体日期中玩的所有游戏的总数)。我希望将行排序按一周内某个游戏的总次数排序(最多玩游戏的周数)。这就是我希望它看到结尾的方式:

final table

我从dickless那里得到了一个很好的建议:如何计算百分比:MongoDB aggregation - how to get a percentage value of how many times an event occurred per day of week

我目前的聚合如下:

    db.games.aggregate([
    { $project: { 
        "_id": 0, 
        "date" : { $dayOfWeek: "$date" }, 
        "title": "$title"

    } },

    { $group: { 
        "_id": { "title": "$title", "date": "$date" }, 
        "total": { $sum: 1 } 

    } }, 

    { $group: { 
        "_id": "$_id.date", 
        "types": { $push: { "title": "$_id.title", total: "$total" } }, 
        "grandTotal": { $sum: "$total" } 

    } }, 

    { $unwind: "$types"}, 

    { $project: { 
        "_id": 0,
        "title": "$types.title", 
        "percentage": { $divide: [ "$types.total", "$grandTotal" ] }, 
        "day": { $arrayElemAt: [ [ "0", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], "$_id" ] } 

    } }, 

    { $group: {
        "_id": "$title", 
        "days": {$push: {"day":"$day", "percentage": "$percentage"} } 

    } } 
])

这是我从中得到的JSON:

/* 1 */
{
    "_id" : "Bomberman",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.2
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Wed",
            "percentage" : 0.09090909090909091
        },
        {
            "day" : "Fri",
            "percentage" : 0.08333333333333333
        }
    ]
},

/* 2 */
{
    "_id" : "GTA",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.4
        },
        {
            "day" : "Mon",
            "percentage" : 0.375
        },
        {
            "day" : "Thu",
            "percentage" : 0.2857142857142857
        },
        {
            "day" : "Wed",
            "percentage" : 0.2727272727272727
        },
        {
            "day" : "Fri",
            "percentage" : 0.3333333333333333
        }
    ]
},

/* 3 */
{
    "_id" : "Forza",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.1
        },
        {
            "day" : "Mon",
            "percentage" : 0.25
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Wed",
            "percentage" : 0.18181818181818182
        },
        {
            "day" : "Fri",
            "percentage" : 0.25
        }
    ]
},

/* 4 */
{
    "_id" : "Pacman",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.1
        },
        {
            "day" : "Mon",
            "percentage" : 0.125
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Wed",
            "percentage" : 0.18181818181818182
        },
        {
            "day" : "Fri",
            "percentage" : 0.08333333333333333
        }
    ]
},

/* 5 */
{
    "_id" : "BattleField",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.2
        },
        {
            "day" : "Mon",
            "percentage" : 0.25
        },
        {
            "day" : "Thu",
            "percentage" : 0.2857142857142857
        },
        {
            "day" : "Wed",
            "percentage" : 0.2727272727272727
        },
        {
            "day" : "Fri",
            "percentage" : 0.25
        }
    ]
}

这是我想要获得的JSON(从最常玩的游戏到最少玩的游戏):

/* 1 */
{
    "_id" : "GTA",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.375
        },
        {
            "day" : "Tue",
            "percentage" : 0.4
        },
        {
            "day" : "Wed",
            "percentage" : 0.2727272727272727
        },
        {
            "day" : "Thu",
            "percentage" : 0.2857142857142857
        },
        {
            "day" : "Fri",
            "percentage" : 0.3333333333333333
        }
    ]
},

/* 2 */
{
    "_id" : "BattleField",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.25
        },
        {
            "day" : "Tue",
            "percentage" : 0.2
        },
        {
            "day" : "Wed",
            "percentage" : 0.2727272727272727
        },
        {
            "day" : "Thu",
            "percentage" : 0.2857142857142857
        },
        {
            "day" : "Fri",
            "percentage" : 0.25
        }
    ]
}

/* 3 */
{
    "_id" : "Forza",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.25
        },
        {
            "day" : "Tue",
            "percentage" : 0.1
        },
        {
            "day" : "Wed",
            "percentage" : 0.18181818181818182
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Fri",
            "percentage" : 0.25
        }
    ]
},

/* 4 */
{
    "_id" : "Pacman",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.125
        },
        {
            "day" : "Tue",
            "percentage" : 0.1
        },
        {
            "day" : "Wed",
            "percentage" : 0.18181818181818182
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Fri",
            "percentage" : 0.08333333333333333
        }
    ]
},

/* 5 */
{
    "_id" : "Bomberman",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.2
        },
        {
            "day" : "Wed",
            "percentage" : 0.09090909090909091
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Fri",
            "percentage" : 0.08333333333333333
        }
    ]
},

数据输入到DB:

[
{"title":"GTA","date":"2017-11-13"},
{"title":"GTA","date":"2017-11-13"},
{"title":"GTA","date":"2017-11-13"},
{"title":"Pacman","date":"2017-11-13"},
{"title":"BattleField","date":"2017-11-13"},
{"title":"BattleField","date":"2017-11-13"},
{"title":"Forza","date":"2017-11-13"},
{"title":"Forza","date":"2017-11-13"},
{"title":"GTA","date":"2017-11-14"},
{"title":"GTA","date":"2017-11-14"},
{"title":"GTA","date":"2017-11-14"},
{"title":"GTA","date":"2017-11-14"},
{"title":"BattleField","date":"2017-11-14"},
{"title":"BattleField","date":"2017-11-14"},
{"title":"Forza","date":"2017-11-14"},
{"title":"Pacman","date":"2017-11-14"},
{"title":"Bomberman","date":"2017-11-14"},
{"title":"Bomberman","date":"2017-11-14"},
{"title":"GTA","date":"2017-11-15"},
{"title":"GTA","date":"2017-11-15"},
{"title":"GTA","date":"2017-11-15"},
{"title":"BattleField","date":"2017-11-15"},
{"title":"BattleField","date":"2017-11-15"},
{"title":"BattleField","date":"2017-11-15"},
{"title":"Forza","date":"2017-11-15"},
{"title":"Forza","date":"2017-11-15"},
{"title":"Pacman","date":"2017-11-15"},
{"title":"Pacman","date":"2017-11-15"},
{"title":"Bomberman","date":"2017-11-15"},
{"title":"GTA","date":"2017-11-16"},
{"title":"GTA","date":"2017-11-16"},
{"title":"BattleField","date":"2017-11-16"},
{"title":"BattleField","date":"2017-11-16"},
{"title":"Forza","date":"2017-11-16"},
{"title":"Bomberman","date":"2017-11-16"},
{"title":"Pacman","date":"2017-11-16"},
{"title":"GTA","date":"2017-11-17"},
{"title":"GTA","date":"2017-11-17"},
{"title":"GTA","date":"2017-11-17"},
{"title":"GTA","date":"2017-11-17"},
{"title":"BattleField","date":"2017-11-17"},
{"title":"BattleField","date":"2017-11-17"},
{"title":"BattleField","date":"2017-11-17"},
{"title":"Forza","date":"2017-11-17"},
{"title":"Forza","date":"2017-11-17"},
{"title":"Forza","date":"2017-11-17"},
{"title":"Bomberman","date":"2017-11-17"},
{"title":"Pacman","date":"2017-11-17"}
]

现在我的问题是如何根据每周最常玩的游戏对行进行排序?我想我需要创建一些子聚合或子管道,我将在哪里计算每个游戏的总播放次数,然后将此结果传递到我的聚合的末尾进行排序,但我找不到这样做的方法。

我真的是一个MongoDB菜鸟,所以我将不胜感激任何建议,谢谢!

1 个答案:

答案 0 :(得分:0)

感谢Alex Blex指出我正确的方法,这是上述问题的解决方案:

db.games.aggregate([
    { $project: { 
        "_id": 0, 
        "date" : { $dayOfWeek: "$date" }, 
        "title": "$title"

    } },

    { $group: { 
        "_id": { "title": "$title", "date": "$date" }, 
        "total": { $sum: 1 } 

    } }, 

    { $group: { 
        "_id": "$_id.date", 
        "types": { $push: { "title": "$_id.title", total: "$total" } }, 
        "grandTotal": { $sum: "$total" } 

    } }, 

    { $sort: {
        "_id": 1 

    } }, // This sorts the arrays with days from Monday to Sunday 

    { $unwind: "$types"}, 

    { $project: { 
        "_id": 0,
        "title": "$types.title", 
        "percentage": { $divide: [ "$types.total", "$grandTotal" ] }, 
        "day": { $arrayElemAt: [ [ "0", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], "$_id" ] }, 
        "supertotal" : "$types.total" // This exposes the total numbers of times a game was played per particular dayOfWeek
    } }, 

    { $group: {
        "_id": "$title", 
        "days": {$push: {"day":"$day", "percentage": "$percentage"} }, 
        "supertotal" : {$sum: "$supertotal"} // This sums the total numbers of times a game was played in a week

    } }, 

    { $sort: {
        "supertotal": -1
    } } // This sorts the documents from the most played game
])

最终JSON:

/* 1 */
{
    "_id" : "GTA",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.375
        },
        {
            "day" : "Tue",
            "percentage" : 0.4
        },
        {
            "day" : "Wed",
            "percentage" : 0.2727272727272727
        },
        {
            "day" : "Thu",
            "percentage" : 0.2857142857142857
        },
        {
            "day" : "Fri",
            "percentage" : 0.3333333333333333
        }
    ],
    "supertotal" : 16.0
},

/* 2 */
{
    "_id" : "BattleField",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.25
        },
        {
            "day" : "Tue",
            "percentage" : 0.2
        },
        {
            "day" : "Wed",
            "percentage" : 0.2727272727272727
        },
        {
            "day" : "Thu",
            "percentage" : 0.2857142857142857
        },
        {
            "day" : "Fri",
            "percentage" : 0.25
        }
    ],
    "supertotal" : 12.0
},

/* 3 */
{
    "_id" : "Forza",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.25
        },
        {
            "day" : "Tue",
            "percentage" : 0.1
        },
        {
            "day" : "Wed",
            "percentage" : 0.18181818181818182
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Fri",
            "percentage" : 0.25
        }
    ],
    "supertotal" : 9.0
},

/* 4 */
{
    "_id" : "Pacman",
    "days" : [
        {
            "day" : "Mon",
            "percentage" : 0.125
        },
        {
            "day" : "Tue",
            "percentage" : 0.1
        },
        {
            "day" : "Wed",
            "percentage" : 0.18181818181818182
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Fri",
            "percentage" : 0.08333333333333333
        }
    ],
    "supertotal" : 6.0
},

/* 5 */
{
    "_id" : "Bomberman",
    "days" : [
        {
            "day" : "Tue",
            "percentage" : 0.2
        },
        {
            "day" : "Wed",
            "percentage" : 0.09090909090909091
        },
        {
            "day" : "Thu",
            "percentage" : 0.14285714285714285
        },
        {
            "day" : "Fri",
            "percentage" : 0.08333333333333333
        }
    ],
    "supertotal" : 5.0
}