Mongodb 从两个数组聚合结果

Mongodb 从两个数组聚合结果,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我是MongoDB的新手,我正在尝试在一个“匹配”集合上聚合一些统计数据,如下所示: { team1: { players: ["player1", "player2"], score: 10 }, team2: { players: ["player3", "player4"], score: 5 } }, { team1: { players: ["player1", "p

我是MongoDB的新手,我正在尝试在一个“匹配”集合上聚合一些统计数据,如下所示:

{
    team1: {
        players: ["player1", "player2"],
        score: 10
    },
    team2: {
        players: ["player3", "player4"],
        score: 5
    }
},
{
    team1: {
        players: ["player1", "player3"],
        score: 15
    },
    team2: {
        players: ["player2", "player4"],
        score: 21
    }
},
{
    team1: {
        players: ["player4", "player1"],
        score: 21
    },
    team2: {
        players: ["player3", "player2"],
        score: 9
    }
},
{
    team1: {
        players: ["player1"],
        score: 5
    },
    team2: {
        players: ["player3"],
        score: 10
    }
}

我希望每个玩家都能获得游戏的赢、输和赢/输比例。我是聚合函数的新手,在运行某些函数时遇到困难。有人能给我指出正确的方向吗?

< P>处理结构中的多个数组并不是一个简单的聚合任务,特别是当你的结果真的要考虑两个数组的组合时。

幸运的是,这里有一些操作和/或技术可以提供帮助,另外还有一个事实,即每一场比赛都由每支球队/每一场比赛和每一个结果的“一组”独特球员组成

最精简的方法是使用MongoDB 2.6及更高版本的功能,将阵列有效地“组合”到单个阵列中进行处理:

db.league.aggregate([
{“$project”:{
“玩家”:{
“$concatarray”:[
{“$map”:{
“输入”:“$team1.players”,
“as”:“el”,
“在”:{
“玩家”:“$$el”,
“赢”:{
“$cond”:{
“如果”:{“$gt”:[“$team1.score”,“$team2.score”]},
"那么":一,,
“其他”:0
}
},
“损失”:{
“$cond”:{
“如果”:{“$lt”:[“$team1.score”,“$team2.score”]},
"那么":一,,
“其他”:0
}
}
}
}},
{“$map”:{
“输入”:“$team2.players”,
“as”:“el”,
“在”:{
“玩家”:“$$el”,
“赢”:{
“$cond”:{
“如果”:{“$gt”:[“$team2.score”,“$team1.score”]},
"那么":一,,
“其他”:0
}
},
“损失”:{
“$cond”:{
“如果”:{“$lt”:[“$team2.score”,“$team1.score”]},
"那么":一,,
“其他”:0
}
}
}
}}
]
}
}},
{“$REWIND”:“$players”},
{“$组”:{
“_id”:“$players.player”,
“赢”{“$sum”:“$players.win”},
“损失”:{“$sum”:“$players.loss”}
}},
{“$project”:{
"赢":一,,
“损失”:1,
“比率”:{“$divide”:[“$win”、“$loss”]}
}},
{“$sort”:{“\u id”:1}
])
这个列表使用的是MongoDB 3.2,但是考虑到每个游戏的玩家列表是“唯一的”,因此是一个“集合”,acutal操作符也可以很容易地被替换。这两个操作符基本上是基于内部操作的输出将一个数组与另一个数组连接起来

对于我们正在使用的那些内部操作,它在线处理每个数组(“team1/team2”),并为每个玩家计算游戏结果是否为“赢/输”。这使以下阶段的工作变得更容易

尽管MongoDB的3.2版和2.6版都引入了运算符,以简化使用阵列的操作,但一般原则是,如果要“聚合”阵列中的数据,则首先使用。这将公开前一个映射中每个游戏中的每个“玩家”数据

现在的问题是如何将每个球员的结果汇总在一起,以及每个总场地的结果。为了获得总和结果的“比率”,使用一个过程在结果值之间引入一个“比率”,然后可选地为每个玩家引入结果键


旧的解决方案 在MongoDB 2.6之前,处理数组的唯一真正工具是第一个
$unwind
。因此,同样的原则在这里发挥作用:

  • 用“赢/输”来“映射”每个阵列
  • 将每个游戏的内容合并为一个“不同列表”
  • 基于公共“玩家”字段的内容总和
  • 方法上唯一的真正区别是,我们将在这里展示的每个游戏的“不同列表”将是“在”分离映射数组之后,而不是每个“游戏/玩家”组合返回一个文档:

    db.league.aggregate([
    {“$REWIND”:“$team1.players”},
    {“$组”:{
    “\u id”:“$\u id”,
    “团队1”:{
    “$push”:{
    “玩家”:“$team1.玩家”,
    “赢”:{
    “$cond”:[
    {“$gt”:[“$team1.score”、“$team2.score”]},
    1.
    0
    ]
    },
    “损失”:{
    “$cond”:[
    {“$lt”:[“$team1.score”,“$team2.score”]},
    1.
    0
    ]
    }
    }
    },
    “team1Score”:{“$first”:“$team1.score”},
    “团队2”:{“$first”:“$team2”}
    }},
    {“$REWIND”:“$team2.players”},
    {“$组”:{
    “\u id”:“$\u id”,
    “团队1”:{“$first”:“$team1”},
    “第二小组”:{
    “$push”:{
    “玩家”:“$team2.玩家”,
    “赢”:{
    “$cond”:[
    {“$gt”:[“$team2.score”,“$team1Score”]},
    1.
    0
    ]
    },
    “损失”:{
    “$cond”:[
    {“$lt”:[“$team2.score”,“$team1Score”]},
    
    db.matches.aggregate([
    {$project:{_id:1, teams:["$team1","$team2"], 
      tscore:{$max:["$team1.score","$team2.score"]}}},
    {$unwind:"$teams"},
    {$unwind:"$teams.players"},
    {$project:{player:"$teams.players", 
      won:{$cond:[{$eq:["$teams.score","$tscore"]},1,0]},
      lost:{$cond:[{$lt:["$teams.score","$tscore"]},1,0]}}},
    {$group:{_id:"$player", won:{$sum:"$won"}, lost:{$sum:"$lost"}}},
    {$project:{_id:0, player:"$_id", won:1, lost:1, 
      ratio:{$cond:[{$eq:[0, "$lost"]},"$won", 
      {$divide:["$won","$lost"]}]}}}
    ])
    
    { 
        "won" : NumberInt(2), 
        "lost" : NumberInt(1), 
        "player" : "player4", 
        "ratio" : 2.0
    }
    { 
        "won" : NumberInt(1), 
        "lost" : NumberInt(3), 
        "player" : "player3", 
        "ratio" : 0.3333333333333333
    }
    { 
        "won" : NumberInt(2), 
        "lost" : NumberInt(1), 
        "player" : "player2", 
        "ratio" : 2.0
    }
    { 
        "won" : NumberInt(2), 
        "lost" : NumberInt(2), 
        "player" : "player1", 
        "ratio" : 1.0
    }