mongoose 在编写聚合查询时需要帮助

628mspwn  于 2022-11-13  发布在  Go
关注(0)|答案(1)|浏览(183)

我只需要“present”中与student _id匹配的数据。但现在,通过此查询,我将获得每个学生数据中的所有学生计数。

学生架构

const StudentSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: [true, "Please Provide Name"],
      maxlength: 100,
      minlength: 2,
    },
    email: {
      type: String,
      required: [true, "Please Provide Email"],
      match: [
        /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
        "Please Provide a Valid Email",
      ],
      unique: true,
    },
    number: {
      type: String,
      required: [true, "Please Provide Number"],
      match: [
        /^(?:(?:\+|0{0,2})91(\s*[\-]\s*)?|[0]?)?[789]\d{9}$/,
        "Please Provide a Valid Number",
      ],
      unique: true,
    },
    rollNumber: {
      type: Number,
      required: [true, "Please Provide Roll Number"],
      maxlength: 5,
    },
    departmentID: {
      type: mongoose.Types.ObjectId,
      ref: "Department",
      required: [true, "Please Provide departmentID"],
    },
    classID: {
      type: mongoose.Types.ObjectId,
      ref: "Class",
      required: [true, "Please Provide classID"],
    },
    position: {
      type: String,
      required: [true, "Please Provide Position"],
      enum: ["Student"],
      default: "Student",
    },
    password: {
      type: String,
      required: [true, "Please Provide Password"],
      minlength: 6,
    },
  },
  { timestamps: true }
);

考勤模式

const mongoose = require("mongoose");
const { Schema } = mongoose;

const AttendanceSchema = new Schema(
  {
    date: {
      type: String,
      required: [true, "Please Provide Date"],
      maxlength: 15,
      minlength: 5,
    },
    subjectID: {
      type: mongoose.Types.ObjectId,
      ref: "Subject",
      required: [true, "Please Provide Subject"],
    },
    studentID: [
      {
        type: mongoose.Types.ObjectId,
        ref: "Student",
        required: [true, "Please Provide Student"],
      },
    ],
    teacherID: {
      type: mongoose.Types.ObjectId,
      ref: "Faculty",
      required: [true, "Please Provide Teacher"],
    },
    classID: {
      type: mongoose.Types.ObjectId,
      ref: "Class",
      required: [true, "Please Provide Class"],
    },
    departmentID: {
      type: mongoose.Types.ObjectId,
      ref: "Department",
      required: [true, "Please Provide Department"],
    },
  },

  { timestamps: true }
);

module.exports = mongoose.model("Attendance", AttendanceSchema);

我正在编写的查询

await StudentSchema.aggregate([
      {
        $match: {
          classID: mongoose.Types.ObjectId(`${req.params.id}`),
        },
      },
      {
        $project: { createdAt: 0, updatedAt: 0, __v: 0, password: 0 },
      },
      {
        $lookup: {
          from: "attendances",
          pipeline: [
            {
              $match: {
                subjectID: mongoose.Types.ObjectId(`${req.params.Sid}`),
              },
            },       
            { $unwind: "$studentID" },
            { $group: { _id: "$studentID", count: { $sum: 1 } } },
          ],
          as: "present",
        },
      },

从该查询中获取的数据

{
    "subject1": [
        {
            "_id": "635d40803352895afffdc294",
            "name": "D R",
            "email": "dugu@gmail.com",
            "number": "9198998888",
            "rollNumber": 202,
            "departmentID": "635a8ca21444a47d65d32c1a",
            "classID": "635a92141a081229013255b4",
            "position": "Student",
            "present": [
                {
                    "_id": "635d40803352895afffdc294",
                    "count": 3
                },
                {
                    "_id": "635eb8898dea5f437789b751",
                    "count": 2
                }
            ]
        },
        {
            "_id": "635eb8898dea5f437789b751",
            "name": "V R",
            "email": "v@gmail.com",
            "number": "9198998899",
            "rollNumber": 203,
            "departmentID": "635a8ca21444a47d65d32c1a",
            "classID": "635a92141a081229013255b4",
            "position": "Student",
            "present": [
                {
                    "_id": "635d40803352895afffdc294",
                    "count": 3
                },
                {
                    "_id": "635eb8898dea5f437789b751",
                    "count": 2
                }
            ]
        }
    ]
}

这种类型的数据我试图实现。只有那些数据将与_id匹配在目前的数组。

{
    "subject1": [
        {
            "_id": "635d40803352895afffdc294",
            "name": "D R",
            "email": "dugu@gmail.com",
            "number": "9198998888",
            "rollNumber": 202,
            "departmentID": "635a8ca21444a47d65d32c1a",
            "classID": "635a92141a081229013255b4",
            "position": "Student",
            "present": [
                {
                    "_id": "635d40803352895afffdc294",
                    "count": 3
                }
            ]
        },
        {
            "_id": "635eb8898dea5f437789b751",
            "name": "V R",
            "email": "v@gmail.com",
            "number": "9198998899",
            "rollNumber": 203,
            "departmentID": "635a8ca21444a47d65d32c1a",
            "classID": "635a92141a081229013255b4",
            "position": "Student",
            "present": [
                {
                    "_id": "635eb8898dea5f437789b751",
                    "count": 2
                }
            ]
        }
    ]
}
rt4zxlrg

rt4zxlrg1#

您只需在$lookup中使用let选项并传递studentId,然后就可以在$lookup阶段中匹配适当的出席人数,如下所示:

{
  $lookup: {
    from: "attendances",
    let: {
      studentID: "$_id"
    },
    pipeline: [
      {
        $match: {
          subjectID: 2,
          $expr: {
            $eq: [
              "$$studentID",
              "$studentID"
            ]
          }
        }
      },
      {
        $unwind: "$studentID"
      },
      {
        $group: {
          _id: "$studentID",
          count: {
            $sum: 1
          }
        }
      }
    ],
    as: "present"
  }
}

Mongo Playground
另一种方法是在结尾处过滤掉present数组,但这会降低效率,并使代码变得丑陋。

相关问题