根据 mongodb 中匹配的数组值过滤文档

问题描述 投票:0回答:1

我有一个名为

students
的mongodb集合,其中有3个文档:

{
  _id: ObjectId('66880dd88517a33fd8141e08'),
  name: 'Mark',
  courses: [
    {course_id: ObjectId('6684e9c8122ef4d77a9dfd1a'), active: true},
    {course_id: ObjectId('6684e9c8122ef4d77a9dfd1b'), active: false}
  ]
}

{
  _id: ObjectId('668626f11b64d2e86632e7cb'),
  name: 'John',
  courses: [
    {course_id: ObjectId('6684e9c8122ef4d77a9dfd1a'), active: false},
    {course_id: ObjectId('6684e9c8122ef4d77a9dfd1b'), active: true}
  ]
}

{
  _id: ObjectId('6684e3b628fcee8f24ead736'),
  name: 'Doe',
  courses: [
    {course_id: ObjectId('6684e9c8122ef4d77a9dfd1a'), active: true},
    {course_id: ObjectId('6684e9c8122ef4d77a9dfd1b'), active: true}
  ]
}

我有另一个名为

courses
的集合,其中有2个文档:

{
  _id: ObjectId('6684e9c8122ef4d77a9dfd1a'),
  note: 'Course on mongodb.'
}

{
  _id: ObjectId('6684e9c8122ef4d77a9dfd1b'),
  note: 'Advanced mongodb course.'
}

我想查询课程集合并获取与给定

_id
匹配的所需文档。该文档应包含一个名为
students
的数组。在这个数组中,每个学生应该包含一个
courses
数组,其中只有那些具有与给定
course_id
_id
相匹配的
active: true
的课程。

假设给定

_id
6684e9c8122ef4d77a9dfd1b
。所以,我想要的输出应该是这样的:

{
  _id: ObjectId('6684e9c8122ef4d77a9dfd1b'),
  note: 'Advanced mongodb course.',
  students: [
    {
      _id: ObjectId('668626f11b64d2e86632e7cb'),
      name: 'John',
      courses: [
        {course_id: ObjectId('6684e9c8122ef4d77a9dfd1b'), active: true}
      ]
    },
    {
      _id: ObjectId('6684e3b628fcee8f24ead736'),
      name: 'Doe',
      courses: [
        {course_id: ObjectId('6684e9c8122ef4d77a9dfd1b'), active: true}
      ]
    }
  ]
}

我正在使用express、mongodb和mongoose。我尝试了这个查询:

app.get('/:id', async function (req, res) {
    try {
        const batch = await Course.aggregate([
            {"$match": {"_id": req.params.id}},
            {"$lookup": {
                    "from": "students",
                    "localField": "_id",
                    "foreignField": "courses.course_id",
                    "as": "students"
                }
            }
        ])

        res.send(batch)
    } catch (error) {
        res.json({
            error: error
        })
    }
})

此查询没有提供我想要的输出。如何获得我想要的输出?

mongodb mongoose
1个回答
0
投票

您的预期结果是您尝试通过匹配

courses
来过滤
req.params.id
数组中的元素。

您可以使用

$set
管道中的
$lookup
阶段执行过滤器:

db.courses.aggregate([
  {
    "$match": {
      "_id": req.params.id  
    }
  },
  {
    "$lookup": {
      "from": "students",
      "localField": "_id",
      "foreignField": "courses.course_id",
      "pipeline": [
        {
          $set: {
            courses: {
              $filter: {
                input: "$courses",
                cond: {
                  $eq: [
                    req.params.id,
                    "$$this.course_id"
                  ]
                }
              }
            }
          }
        }
      ],
      "as": "students"
    }
  }
])

演示@Mongo Playground

© www.soinside.com 2019 - 2024. All rights reserved.