MongoDB 连接多个集合、组、排序推送数组并重组结果的查询

MongoDB query that joins multiple collections, groups, sorts push array and restructures the result

MongoDB游乐场linkhere。下面列出了 DataDesired Result。学生可以一次又一次地学习同一门课程。我希望结果将学生与 _id: 1 匹配,然后按课程分组,然后按学期开始日期排序,并且仅 return 最近学期。这可能吗?

数据

db={
  registers: [
    {
      _id: 1,
      student: 1,
      school: 1,
      course: 1,
      semester: 1,
      grade: 59
    },
    {
      _id: 2,
      student: 1,
      school: 1,
      course: 1,
      semester: 2,
      grade: 99
    },
    {
      _id: 3,
      student: 1,
      school: 2,
      course: 2,
      semester: 3,
      grade: 100
    }
  ],
  students: [
    {
      _id: 1,
      name: "Student1"
    },
    {
      _id: 2,
      name: "Student2"
    }
  ],
  schools: [
    {
      _id: 1,
      name: "Zefram Cochrane High School"
    },
    {
      _id: 2,
      name: "Star Fleet Academy"
    }
  ],
  courses: [
    {
      _id: 1,
      name: "Warp Theory"
    },
    {
      _id: 2,
      name: "Temporal Mechanics"
    }
  ],
  semesters: [
    {
      _id: 1,
      name: "Fall 2320",
      startDate: ISODate("2320-02-01"),
      endDate: ISODate("2320-05-31")
    },
    {
      _id: 2,
      name: "Fall 2320",
      startDate: ISODate("2320-09-01"),
      endDate: ISODate("2320-12-31")
    },
    {
      _id: 3,
      name: "Spring 2321",
      startDate: ISODate("2321-02-01"),
      endDate: ISODate("2321-05-31")
    }
  ]
}

期望的结果

[
  {
    "course": {
      "name": "Warp Theory"
    },
    "grade": 99,
    "school": {
      "name": "Zefram Cochrane High School"
    },
    "semester": {
      "endDate": ISODate("2320-12-31T00:00:00Z"),
      "name": "Fall 2320",
      "startDate": ISODate("2320-09-01T00:00:00Z")
    },
    "student": {
      "name": "Student1"
    }
  },
  {
    "course": {
      "name": "Temporal Mechanics"
    },
    "grade": 100,
    "school": {
      "name": "Star Fleet Academy"
    },
    "semester": {
      "endDate": ISODate("2321-05-31T00:00:00Z"),
      "name": "Spring 2321",
      "startDate": ISODate("2321-02-01T00:00:00Z")
    },
    "student": {
      "name": "Student1"
    }
  }
]

我将简要介绍这些变化:

  • 过滤最大开始日期
  • 包含的成绩
  • 已尝试稍微改进您要求的格式。 (可以回滚)

输出

[
  {
    "course": "Warp Theory",
    "grade": 99,
    "school": "Zefram Cochrane High School",
    "semester": {
      "endDate": ISODate("2320-12-31T00:00:00Z"),
      "startDate": ISODate("2320-09-01T00:00:00Z")
    },
    "student": "Student1"
  },
  {
    "course": "Temporal Mechanics",
    "grade": 100,
    "school": "Star Fleet Academy",
    "semester": {
      "endDate": ISODate("2321-05-31T00:00:00Z"),
      "startDate": ISODate("2321-02-01T00:00:00Z")
    },
    "student": "Student1"
  }
]

管道

db.registers.aggregate([
  {
    $match: {
      student: 1
    }
  },
  {
    $lookup: {
      from: "students",
      localField: "student",
      foreignField: "_id",
      as: "student"
    }
  },
  {
    $unwind: "$student"
  },
  {
    $lookup: {
      from: "schools",
      localField: "school",
      foreignField: "_id",
      as: "school"
    }
  },
  {
    $unwind: "$school"
  },
  {
    $lookup: {
      from: "courses",
      localField: "course",
      foreignField: "_id",
      as: "course"
    }
  },
  {
    $unwind: "$course"
  },
  {
    $lookup: {
      from: "semesters",
      localField: "semester",
      foreignField: "_id",
      as: "semester"
    },
    
  },
  {
    $unwind: "$semester"
  },
  {
    "$addFields": {
      "semester.grade": "$grade"
    }
  },
  {
    $group: {
      _id: {
        course: "$course.name",
        school: "$school.name",
        student: "$student.name"
      },
      semester: {
        $push: "$semester"
      },
      max: {
        $max: "$semester.startDate"
      }
    }
  },
  {
    $addFields: {
      course: "$_id.course",
      school: "$_id.school",
      student: "$_id.student",
      semester: {
        $filter: {
          input: "$semester",
          as: "s",
          cond: {
            $eq: [
              "$$s.startDate",
              "$max"
            ]
          }
        }
      }
    }
  },
  {
    $addFields: {
      "grade": "$semester.grade"
    }
  },
  {
    $unset: [
      "max",
      "_id",
      "semester._id",
      "semester.grade",
      "semester.name"
    ]
  },
  {
    $unwind: "$semester"
  },
  {
    $unwind: "$grade"
  }
])