加入两个 collections,id 存储在 mongodb 的 objects 数组中

Join two collections with id stored in array of objects in mongodb

我有两个 collection 名字是 学校 & 学生

学校Collection

   {
      _id: ObjectId("60008e81d186a82fdc4ff2b7"),
      name: String,
      branch: String,  
      class: [{
             "active" : true,
             "_id" : ObjectId("6001e6871d985e477b61b43f"),
             "name" : "I",
             "order" : 1
        }, 
        {
             "active" : true,
             "_id" : ObjectId("6001e68f1d985e477b61b444"),
             "name" : "II",
             "order" : 2
        }]
   }

学生Collection

  {
      _id: ObjectId("6002def815eccd53a596f830"),
      schoolId: ObjectId("60008e81d186a82fdc4ff2b7"),
      sessionId: ObjectId("60008e81d186a82fdc4ff2b9"),
      class: ObjectId("6001e6871d985e477b61b43f"),
   }

我想在单个查询中获取学生Collection的数据。

我 class id 存储在 Student Collection 中,针对 id 的数据存储在 School Collection 下的 class 键下,这是 objects.

的数组

你能帮我用这个 id 在学生 collection 中获取 class object 吗?

我想要的输出:

data: {
  _id: ObjectId("6002def815eccd53a596f830"),
  schoolId: ObjectId("60008e81d186a82fdc4ff2b7"),
  sessionId: ObjectId("60008e81d186a82fdc4ff2b9"),
  class: ObjectId("6001e6871d985e477b61b43f"),
  classData: [{
        "active" : true,
        "_id" : ObjectId("6001e6871d985e477b61b43f"),
        "name" : "I",
        "order" : 1
    }]

}

所以我尝试了这个但是没有用:

const students = await this.studentModel.aggregate([
{
  $lookup: {
    from: 'School',
    let: { classId: '$class' },
    pipeline: [
      {
        $match: {
          $expr: { $eq: ['$$classId', '$class._id'] },
        },
      },
    ],
    as: 'classData',
  },
},
]);
  • $lookup,在let
  • 中传递schoolIdclass
  • $match 学号条件
  • $filter 迭代 class 的循环并过滤特定的 class 对象
  • $arrayElemAt 将从 $filter
  • 返回的结果中获取对象
  • $replaceRoot 将对象替换为 root
const students = await this.studentModel.aggregate([
  {
    $lookup: {
      from: "School",
      let: {
        schoolId: "$schoolId",
        classId: "$class"
      },
      pipeline: [
        { $match: { $expr: { $eq: ["$$schoolId", "$_id"] } } },
        {
          $replaceRoot: {
            newRoot: {
              $arrayElemAt: [
                {
                  $filter: {
                    input: "$class",
                    cond: { $eq: ["$$this._id", "$$classId"] }
                  }
                },
                0
              ]
            }
          }
        }
      ],
      as: "classData"
    }
  }
])

Playground