我需要从查询中获取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。
答案 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
}
注意:即使您在数据库中拥有零用户或单用户,代码也会起作用。但在第二种情况下,您将获得第二个最具发挥作用的用户的统计数据的空文档。这很公平。