mongo聚合 - 为字段的不同值组积累

时间:2016-09-14 15:43:58

标签: javascript mongodb meteor aggregation-framework

如果我有Player格式的文件

{name: String, score: Int}

我有Group个文档,其中组代表玩家列表

{groupName: String, players: [ObjectID]}

玩家可以属于多个群组。

我希望对Player文档进行汇总,按Group分组(例如,使用一个汇总管道获取每个组的玩家总数和得分)。

我意识到的选项:

=>让Player个文档返回指向与之关联的Group个文档的指针,然后$group指向GroupID。但我更喜欢不必修改Player集合。 (也许有一种方法可以在管道中向文档添加" GroupID?)

=>为每个组单独调用并使用$match阶段过滤到当前正在查询的组中的玩家。但我更愿意做一个简单的电话。

如何实现这样的聚合? MongoDB聚合是否有适用于此的东西?

(顺便说一下,在正在进行通话的内存中,让彼此映射的组和玩家并不是一个问题。因此,将玩家列表作为参数传递的选项确实是公平的游戏。)

2 个答案:

答案 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"
  }}  
])