如果我有Player
格式的文件
{name: String, score: Int}
我有Group
个文档,其中组代表玩家列表
{groupName: String, players: [ObjectID]}
玩家可以属于多个群组。
我希望对Player
文档进行汇总,按Group
分组(例如,使用一个汇总管道获取每个组的玩家总数和得分)。
我意识到的选项:
=>让Player
个文档返回指向与之关联的Group
个文档的指针,然后$group
指向GroupID
。但我更喜欢不必修改Player
集合。 (也许有一种方法可以在管道中向文档添加" GroupID
?)
=>为每个组单独调用并使用$match
阶段过滤到当前正在查询的组中的玩家。但我更愿意做一个简单的电话。
如何实现这样的聚合? MongoDB聚合是否有适用于此的东西?
(顺便说一下,在正在进行通话的内存中,让彼此映射的组和玩家并不是一个问题。因此,将玩家列表作为参数传递的选项确实是公平的游戏。)
答案 0 :(得分:1)
您可以使用 $lookup
运算符。考虑运行以下聚合管道:
Mongo shell:
db.group.aggregate([
{ "$unwind": "$players" },
{
"$lookup": {
"from": "players",
"localField": "players",
"foreignField": "_id",
"as": "players_join"
}
},
{ "$unwind": "$players_join" },
{
"$group": {
"_id": {
"groupName": "$groupName",
"name": "$players_join.name"
},
"totalScore": { "$sum": "$players_join.score" }
}
}
])
您可以通过获取包含一些Mongo方法的聚合框架包来添加对聚合的支持。只需流星添加 meteorhacks:aggregate
,您应该开展业务。这将为Meteor中的集合添加聚合方法。
答案 1 :(得分:1)
除了@Chridam回答,为了避免混淆集合/字段/展开别名,我建议:
db.Group.aggregate( [
{$unwind:"$players"},
{$lookup: {
from:"Player",
localField:"players",
foreignField:"_id",
as:"P" }
},
{$unwind:"$P"},
{"$group":{
total: {$sum:"$P.score"},
_id:"$_id"
}}
])