【问题标题】:$lookup on ObjectId's in an array and project it to same array$lookup 查找数组中的 ObjectId 并将其投影到同一个数组
【发布时间】:2021-09-22 06:40:34
【问题描述】:

我有一个如下的类架构

const AttendanceSchema = new mongoose.Schema({
    date: Date,
    records: [{
        studentId: {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'User'
        },
        attendance: Boolean
    }]
})

var ClassSchema = new mongoose.Schema({
    title: String,
    description: String,
    attendances: [AttendanceSchema]
});

这里我有出勤对象来维持班级学生的出勤率。因此,每天,每当我们下课时,我们都可以 $push 一个带有日期和出勤记录详细信息的对象。 一个 Class 对象看起来像这样

{
    title: "Class Name",
    description: "Description",
    attendances: [
    {
        _id: "60ed395fb06f1254b0771ce1",
        date: "2021-07-13T06:57:00.000+00:00",
        records: [
            {
                attendance: true,
                _id: "60ed395fb06f1254b0771ce2",
                studentId: "60e6c440c133a9b590f510d5"
            },
            {
                attendance: false,
                _id: "60ed395fb06f1254b0771ce3",
                studentId: "60e6c4cb7be1ce4b647c546f"
            }
        ]
    },
    {
        _id: "60ed395fb06f1254b0771ce4",
        date: "2021-07-14T06:57:00.000+00:00"
        records: [
            {
                attendance: true,
                _id: "60ed395fb06f1254b0771ce5",
                studentId: "60e6c440c133a9b590f510d5"
            },
            {
                attendance: true,
                _id: "60ed395fb06f1254b0771ce6",
                studentId: "60e6c4cb7be1ce4b647c546f"
            }
        ]
    }
    ]
}

在这里您可以看到每个记录对象都包含一个具有对象 id 的对象。我想以相同的格式获取学生的详细信息 期望的输出

title: "Class Name"
description: "Description"
attendances: [
   {
      _id: 60ed395fb06f1254b0771ce1
      date: 2021-07-13T06:57:00.000+00:00
      records: [
         {
            attendance: true
            _id: 60ed395fb06f1254b0771ce2
            studentId: 60e6c440c133a9b590f510d5
            _studentDetail: {
               name: "Name"
               detail: ...
            }
         },
         {
            attendance: false
            _id: 60ed395fb06f1254b0771ce3
            studentId: 60e6c4cb7be1ce4b647c546f
         }
      ]
   },
   ...
]

如果我使用 $lookup,我只能在单独的对象中获取学生详细信息。我怎样才能得到它?

【问题讨论】:

  • 这是否回答了您的问题:stackoverflow.com/questions/60740560/… ?
  • 不,在我的情况下,本地字段位于数组内部的数组中。在该示例中,您可以将上下文对象想象为数组。
  • 这是相同的模式只是更多的嵌套级别,看我的回答

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

由于您的数据结构嵌套很深,您需要在运行$lookup 之前提取所有studentIds。可以使用$reduce 运算符和$addFields

从第二个集合中获取所有学生后,每个文档中都有两个数组:studentsattendances。然后,您需要通过运行多个 $map 运算符以及 $mergeObjects$filter 来合并它们,以获得每个 record 的匹配学生:

db.Attendance.aggregate([
    {
        $addFields: {
            students: {
                $reduce: {
                    input: "$attendances",
                    initialValue: [],
                    in: { $setUnion: [ "$$value", "$$this.records.studentId" ] }
                }
            }
        }
    },
    {
        $lookup: {
            from: "Students",
            localField: "students",
            foreignField: "_id",
            as: "students"
        }
    },
    {
        $project: {
            title: 1,
            description: 1,
            attendances: {
                $map: {
                    input: "$attendances",
                    as: "a",
                    in: {
                        $mergeObjects: [
                            "$$a",
                            {
                                records: {
                                    $map: {
                                        input: "$$a.records",
                                        as: "r",
                                        in: {
                                            attendance: "$$r.attendance",
                                            _id: "$$r._id",
                                            student: {
                                                $arrayElemAt: [
                                                    { $filter: { input: "$students", cond: { $eq: [ "$$this._id", "$$r.studentId" ] } } }
                                                    , 0
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
])

Mongo Playground

【讨论】:

    猜你喜欢
    • 2016-04-30
    • 2018-01-10
    • 2021-08-25
    相关资源
    最近更新 更多