如何使用聚合有条件地进行分组

时间:2014-08-26 13:52:18

标签: mongodb mongodb-query nosql

我目前正在尝试弄清楚如何为数组中的某些对象创建组。例如,根据下面的文档结构,我想创建一个$group,其中只有id为5和4的人才会被处理到该组中。

我在伪代码中试图实现的目标:

        { $unwind:"$people" },

        { $group: {
            if("$people.id"===5 || "$people.id"===4){
                  _id: $people.id
                  averageScore: {$avg: "$score"}
            }
        }} 

这将返回两个文档,一个文档的_id为5,averageScore为10,一个文档为_id 4,averageScore为13.5

示例文档结构:

doc 1

{
    gameId:394028,
    people: [{
      id: 5,
      score: 10,
      mapSide: 'left'
   },{
      id: 4,
      score: 14,
      mapSide: 'right'
   },{
      id: 1,
      score: 11,
      mapSide: 'right'
   },{
      id: 2,
      score: 12,
      mapSide: 'left'
   }]
}

doc 2

{
    gameId:394028,
    people: [{
      id: 7,
      score: 5,
      mapSide: 'left'
   },{
      id: 9,
      score: 10,
      mapSide: 'right'
   },{
      id: 4,
      score: 13,
      mapSide: 'right'
   },{
      id: 1,
      score: 12
      mapSide: 'left'
   }]
}

1 个答案:

答案 0 :(得分:2)

你应该能够使用像

这样的东西
{ $unwind:"$people" },
{ $match:{$or :[{'people.id' : 4}, {'people.id' :5}]} },
{ $group: {_id:"$people.id"
           averageScore: {$avg: "$score"}}

$match基本上会过滤你的展开集合,就像find命令一样(采用相同的语法)并将匹配的文档传递给下一个阶段。如果您要匹配很多ID,则可以将$or替换为'people.id':{$in:[4,5]}


修改:评论后此管道的详细说明:

问题的前两个管道阶段到doc1会发生什么:

  • { $unwind:"$people" } 结果:

    {gameId:394028, people: {id: 5, score: 10, mapSide: 'left'}},
    {gameId:394028, people: {id: 4, score: 14, mapSide: 'right'}},
    {gameId:394028, people: {id: 1, score: 11, mapSide: 'right'}},
    {gameId:394028, people: {id: 2, score: 12, mapSide: 'left' }},
    
  • { $match:{$or :[{'people.id' : 4}, {'people.id' :5}]} }结果:

    {gameId:394028, people: {id: 5, score: 10, mapSide: 'left'}},
    {gameId:394028, people: {id: 4, score: 14, mapSide: 'right'}},
    

之后,您仍然可以访问$group阶段原始文档中可用的所有字段。