获取第一个聚合结果并将所有其他结果汇总到其他元素中

时间:2017-01-27 15:10:57

标签: mongodb mongodb-query aggregation-framework

我需要从查询中获取N个顶级项目,并将所有其他项目(不在N顶部)分组到另一个元素中。

例如,考虑一个包含以下文档的集合:

{user: "Ana", post: "A" },
{user: "Ana", post: "B" },
{user: "Ana", post: "C" },
{user: "Ana", post: "D" },
{user: "Bruce", post: "E" },
{user: "Bruce", post: "F" },
{user: "Bruce", post: "G" },
{user: "Cami", post: "H" },
{user: "Cami", post: "I" },
{user: "John", post: "J" },
{user: "Peter", post: "K" },
{user: "Helena", post: "L" }

我希望获得最多贡献的2个用户,并将所有其他用户聚合在一个额外的输出项中。例如:

{user: "Ana", count: 4},
{user: "Bruce", count: 3},
{user: "All others guys", count: 5}

现在我正在使用“聚合”功能:

db.MyTest.aggregate(
[
    {
        $group: {
            "_id": "$user",
            count: {
                $sum: 1
            }
        }
    },
    {
        $sort: {
            count: -1,
            userName: 1
        }
    }
]
);

我不知道如何对待“所有其他人”项目。我的函数返回以下结果:

{_id: "Ana", count: 4},
{_id: "Bruce", count: 3},
{_id: "Cami", count: 2},
{_id: "John", count: 1},
{_id: "Peter", count: 1},
{_id: "Helena", count: 1} 

任何想法如何直接在mongo中使用单个查询?

P.S。:我正在使用Mongo 3.2.11。

1 个答案:

答案 0 :(得分:1)

订购统计信息后,您可以将所有用户统计信息推送到数组,然后从该数组中按索引获取所需项目,并将所有其他项目切片以便稍后聚合其统计信息:

db.users.aggregate([
    {$group: {_id:"$user", count:{$sum:1}}},
    {$sort: {count:-1}},
    // Split stats into first, second and others
    {$group: {_id:1, users:{$push:{user:"$_id", count:"$count"}}}},
    {$project: {
        first : {$arrayElemAt: ["$users", 0]},
        second: {$arrayElemAt: ["$users", 1]},
        others: {$slice:["$users", 2, {$size: "$users"}]}
      }
    },
    // Calculate count for all other guys
    {$project: {
         stats: [
            "$first",
            "$second",
            {
                user: "All other guys",
                count: {$sum: "$others.count"}
            }
         ]
      }
    },
    // Bring embeded documents to top level
    {$unwind: "$stats"}, 
    {$project: { _id:0, user: "$stats.user", count: "$stats.count" }}        
])

输出:

{
    "user" : "Ana",
    "count" : 4
}, 
{
    "user" : "Bruce",
    "count" : 3
}, 
{
    "user" : "All other guys",
    "count" : 5
}

注意:即使您在数据库中拥有零用户或单用户,代码也会起作用。但在第二种情况下,您将获得第二个最具发挥作用的用户的统计数据的空文档。这很公平。