连接多个集合,组,对推数组进行排序并重组结果的MongoDB查询

时间:2020-11-10 23:58:45

标签: mongodb aggregate pipeline

MongoDB Playground链接here。以下列出了DataDesired Result。学生可以一次又一次地参加同一门课程。我希望结果与_id: 1的学生匹配,然后按课程分组,然后按学期排序startDate并仅返回最近的学期。这可能吗?

数据

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

1 个答案:

答案 0 :(得分:1)

我将仅简要介绍这些更改:

  • 过滤最大startDate
  • 包含的成绩
  • 试图略微改善您要求的格式。 (可以回滚)

输出

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