Mongodb 如何使用聚合有条件地对$group进行分组

Mongodb 如何使用聚合有条件地对$group进行分组,mongodb,mongodb-query,nosql,Mongodb,Mongodb Query,Nosql,我目前正在研究如何为数组中的某些对象创建一个组。例如,根据下面的文档结构,我想创建一个$group,其中只有id为5和4的人被处理到该组中 我试图在伪代码中实现的是: { $unwind:"$people" }, { $group: { if("$people.id"===5 || "$people.id"===4){ _id: $people.id averageS

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

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

        { $unwind:"$people" },

        { $group: {
            if("$people.id"===5 || "$people.id"===4){
                  _id: $people.id
                  averageScore: {$avg: "$score"}
            }
        }} 
这将返回两个文档,一个文档的
\u id
为5,平均分数
为10,另一个文档的
\u id
为4,平均分数
为13.5

文档结构示例:

文件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'
   }]
}
文件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'
   }]
}

你应该可以选择这样的方式

{ $unwind:"$people" },
{ $match:{$or :[{'people.id' : 4}, {'people.id' :5}]} },
{ $group: {_id:"$people.id"
           averageScore: {$avg: "$score"}}
$match
基本上会像find命令一样过滤未缠绕的集合(采用相同的语法),并将匹配的文档传递到下一阶段。如果要匹配的id很多,可以将
$或
替换为
'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'}},
    {gameId:394028, people: {id: 1, score: 11, mapSide: 'right'}},
    {gameId:394028, people: {id: 2, score: 12, mapSide: 'left' }},
    
    {gameId:394028, people: {id: 5, score: 10, mapSide: 'left'}},
    {gameId:394028, people: {id: 4, score: 14, mapSide: 'right'}},
    

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

嘿,这很好地工作了,但我有一个问题供我自己理解-我仍然可以从$group管道访问gameId(这是我想要的,因为我有其他信息,如gameDuration等)我好奇的是,如果在$match管道中删除了这些信息(我假设是这样),我怎么还能访问这些信息。我假设我只能访问匹配的“人员集合”中的信息,但我仍然可以访问外部信息。希望这有意义@Joel在答案中添加了前两个阶段的细节,作为解释,希望helps@Trubert非常感谢,这就很清楚了。