如何访问 MongoDB 文档中数组中的对象?

How to access an object within an array within a MongoDB document?

-- 底部的答案 --

我和我的项目合作伙伴正在尝试弄清楚如何访问数组中的对象,即我们 MongoDB 数据库中文档中的对象。

我们正在构建一个网站,用户可以在其中创建作业(在特定课程中),并且在创建该作业后,可以导航到该课程的主页,并访问该作业的页面(这将是一个通用的 .ejs 模板根据我们创建的任务填写正确信息的页面)。

例如,在 CS 212 课程中,我们创建了作业 1(包含一些问题和答案)和作业 2。我们导航到 CS 212 的页面,单击作业 1,它应该会显示这些问题和答案。

我们想使用我们在数据库中创建的作业 ID 来访问作业的数据库数据,但是,“Courses.findOne( {assignments: assignmentID} )”(类似的东西)正在返回整个课程 (CS 212) 对象,而不仅仅是作业。

我们的架构如下:

const CourseSchema = new mongoose.Schema(
    {
        CourseNum: {
            type: String,
            required: true,
        },
        CourseName: {
            type: String,
            required: true,
        },
        CourseID: {
            type: String,
            required: true,
        },
        CourseCredits: {
            type: Number,
            required: true
        },
        CourseDescription: {
            type: String,
            required: true,
        },
        CourseMaterials: {
            type: String,
            required: true,
        },
        Instructors: {
            type: [String],
            required: true
        },
        Students: [String],
        assignments: [assignmentSchema]
    },
    {   timestamps: true,
        collection: 'courses' }
)

这是我们的主要模型,称为课程,在作业内部(如您所见),我们将子文档作为数组中的另一个模式传入:

const mongoose = require('mongoose');

// const assignmentSchema = require("/assignment");
const assignmentSchema = new mongoose.Schema(
    {
        assignmentId: {
            type: String,
            required: true,
            unique: true
        },
        assignmentName: {
            type: String,
            required: true,
        },
        questions: {
            type: [String],
        },
        answers: {
            type: [String],
        }
    },
    {
        timestamps: true,
        collection: 'assignments'
    }
)

如您所见,我们正在尝试根据在课程仪表板页面的 post 方法中传入的值访问特定的作业 ID,然后导航到我们的 generic/dynamically填充的作业页面,但特别是我们的 AssignmentID 指定的页面。

我们的代码如下:

app.get("/assignXpage/:assign", requireAuth('instructor'), function (req, res){
  let input = req.params.assign;
  // let course = req.cookies.courseid;
  console.log('input', input)
  Course.findOne({"Course.assignments": { assignmentId: input}})
    .then((result) => {
      console.log(result)
      res.render("pages/Instructor/assignmentXpage", { assign: result });
    })
    .catch((err) => {
      console.log(err);
    });
});

以下代码:

let input = req.params.assign;

存储了我们要查找的特定作业的 ID,但 findOne(或查找)方法无法正常工作,returns 整个 CS 212 课程。

任何帮助将不胜感激,谢谢!

-- 我们给出的答案 -- 我们使用的确切解决方案(基于以下用户的回答)是:

Course.findOne({ "assignments.assignmentId": input })
          .select({ assignments: { $elemMatch: { assignmentId: input } } })
          .then((result) => {
            res.render("pages/Student/assignmentXpagest", { assign: result });
          })
          .catch((err) => {
            console.log(err);
          });

您可以在项目选项中使用 $elematch 作为上述响应。 您的查询将类似于此。

Course.findOne({'assignments.assignmentId': input}, {_id: 0, assignments: {$elemMatch: { assignmentId: '1'}}, CourseName: 1})

你必须在项目字段的响应中添加你想要的字段,就像我添加 CourseName 一样。

您也可以使用 $ projection 运算符执行此操作,其中投影对象字段名称中的 $ 表示查询中该字段的第一个匹配数组元素的索引。

 Course.findOne({'assignments.assignmentId': input}, {_id: 0, 'assignments.$': 1,  CourseName: 1})

在上面的两个答案中,它 return 只有第一个元素与查询匹配。如果有多个对象与同一个分配 ID 相关,则必须使用 aggregate