简体   繁体   English

对数组内的对象进行分组 - MongoDB 聚合

[英]Grouping objects inside an array - MongoDB Aggregation

I am using a training grades database from MongoDB.我正在使用来自 MongoDB 的培训成绩数据库 It is structured as follows.它的结构如下。

    "_id": {
        "$oid": "56d5f7eb604eb380b0d8d8fa"
    },
    "class_id": {
        "$numberDouble": "173"
    },
    "scores": [
        {
            "score": {
                "$numberDouble": "19.81430597438296"
            },
            "type": "exam"
        },
        {
            "score": {
                "$numberDouble": "16.851404299968642"
            },
            "type": "quiz"
        },
        {
            "score": {
                "$numberDouble": "60.108751761488186"
            },
            "type": "homework"
        },
        {
            "score": {
                "$numberDouble": "22.886167083915776"
            },
            "type": "homework"
        }
    ],
    "student_id": {
        "$numberDouble": "4"
    }
}

I am trying to run aggregation which returns all documents grouped first by class_id and then by student_id with all homework scores like the following.我正在尝试运行聚合,它返回首先按 class_id 分组的所有文档,然后按 student_id 分组,所有作业分数如下所示。

{
   class_id: 3,
   all_scores: [
      {
         student_id: 110, 
         scores : [
            {
               type: "homework", 
               score: 89.98
            },
            {
               type: "homework", 
               score: 90.98
            },
         ]
      },
      {
         student_id:190, 
         scores : [
            {
               type: "homework", 
               score: 18.98
            },
            {
               type: "homework", 
               score: 99.98
            },
         ]
      },
   ]
}
   

I am running the following aggregation function.我正在运行以下聚合函数。

[
  {
    '$unwind': {
      'path': '$scores'
    }
  }, {
    '$match': {
      'scores.type': 'homework'
    }
  }, {
    '$group': {
      '_id': '$class_id', 
      'scores': {
        '$push': {
          'type': '$scores.type', 
          'score': '$scores.score', 
          'student_id': '$student_id'
        }
      }
    }
  }
]
   

But it is returning the following result:但它返回以下结果:

{
   _id: 3, 
   scores: [
      {
         "type": "homework",
         "score": 89.98, 
         "student_id": 110
      }, 
      {
         "type": "homework",
         "score": 90.98, 
         "student_id": 110
      }, 
      {
         "type": "homework",
         "score": 18.98, 
         "student_id": 190
      }, 
      {
         "type": "homework",
         "score": 99.98, 
         "student_id": 190
      },
   ]
}

If even if there are multiple objects in the scores array, it is not combining them with the student_id group and shows them separate.如果即使scores数组中有多个对象,也不会将它们与student_id组合并,而是将它们分开显示。 I am not sure of what I should add to the aggregation.我不确定我应该在聚合中添加什么。 Any help would be appreciated!任何帮助,将不胜感激!

Try With this Aggregate Query,尝试使用此聚合查询,

[
  {
    '$unwind': {
      'path': '$scores'
    }
  }, {
    '$match': {
      'scores.type': 'homework'
    }
  }, {
    '$group': {
      '_id': {class_id:'$class_id',
              student_id:'$student_id'}, 
      'scores': {
        '$push': {
          'type': '$scores.type', 
          'score': '$scores.score'
        }
      }
    }
  }
]

Mongo Playground Link Mongo游乐场链接

I think this is the precise format you wanted.我认为这是您想要的精确格式。

The aggregation pipeline:聚合管道:

[
  {
    "$unwind": {
      "path": "$scores"
    }
  },
  {
    "$match": {
      "scores.type": "homework"
    }
  },
  {
    "$group": {
      "_id": {
        "class_id": "$class_id",
        "student_id": "$student_id"
      },
      "scores": {
        "$push": {
          "type": "$scores.type",
          "score": "$scores.score"
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id.class_id",
      all_scores: {
        $push: {
          "student_id": "$_id.student_id",
          scores: "$scores"
        }
      }
    }
  },
  {
    "$project": {
      _id: 0,
      class_id: "$_id",
      all_scores: "$all_scores"
    }
  }
]

The first two stages of the pipeline I guess are simply to filter out the non-homework documents.我猜管道的前两个阶段只是过滤掉非作业文档。

To perform a "nested grouping" of sorts, where not only does the data have an outer grouping over class_id but an inner grouping in the scores over student_id , first we group the data in the first $group stage over both those fields, much like described here .要执行各种“嵌套分组”,其中不仅数据在class_id有外部分组,而且在student_id上的scores有内部分组,首先我们在这两个字段的第一个$group阶段对数据进行$group ,很像在这里描述。

The scores array in each document here will be the same as the arrays we need in each inner grouping (over student_id ), so, now we can just group by the class_name (in the _id object after the result of the first group stage) and add the student_id along with the scores in each object to push in the all_scores array.此处每个文档中的scores数组将与我们在每个内部分组(通过student_id )中所需的数组相同,因此,现在我们只需按class_name分组(在第一个小组阶段结果之后的_id对象中)和添加student_id以及每个对象中的scores以推入all_scores数组。 Then the final $project stage is pretty trivial, just to get it in the format that we want.然后最后的$project阶段就很简单了,只是把它变成我们想要的格式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM