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

时间:2020-09-19 06:03:53

标签: node.js mongodb express aggregation

我正在使用来自MongoDB的training grades database。其结构如下。

    "_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"
    }
}

我正在尝试进行汇总,以返回所有文件,这些文件首先按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
            },
         ]
      },
   ]
}
   

我正在运行以下聚合函数。

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

但是它返回以下结果:

{
   _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
      },
   ]
}

即使在scores数组中有多个对象,它也不会将它们与student_id组组合在一起并单独显示。我不确定应该添加到聚合中的内容。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:0)

尝试使用此汇总查询,

[
  {
    '$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'
        }
      }
    }
  }
]

答案 1 :(得分:0)

Mongo Playground Link

我认为这是您想要的准确格式。

聚合管道:

[
  {
    "$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"
    }
  }
]

我想管道的前两个阶段只是过滤掉非作业文档。

要执行各种“嵌套分组”,其中数据不仅在class_id上具有外部分组,而且在scores上具有student_id中的内部分组,首先我们将其分组$group的第一个阶段中的数据都在这两个字段中,就像描述的here一样。

此处每个文档中的scores数组将与我们每个内部分组(在student_id上)所需的数组相同,因此,现在我们可以按class_name进行分组(在第一个小组讨论的结果之后的_id对象中),并将student_idscores一起添加到每个对象中,以推入all_scores数组。那么最后的$project阶段就很简单了,只是以我们想要的格式来获取它即可。