Home > database >  How to access an object within an array within a MongoDB document?
How to access an object within an array within a MongoDB document?

Time:12-21

My project partner and I are trying to figure out how to access an object that is within an array, that is within a document in our MongoDB database.

We are building a website where users can create an assignment (within a specific course), and after creating that assignment, can navigate to that course's homepage, and access the assignment's page (which will be a generic .ejs template page that fills up with the proper information, based off the assignment we created).

For example, within the course CS 212, we created assignment 1 (filled with a few questions and answers) and assignment 2. We navigate to CS 212's page, click on Assignment 1, and it should display those questions and answers.

We would like to access the assignment's database data using the assignment's ID that we created within the database, however, the "Courses.findOne( {assignments: assignmentID} )" (something along those lines) is returning the entire course (CS 212) object instead of just the assignment.

Our Schema is as follows:

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' }
)

This is our main Model, called Course, and inside of assignments (as you can see above), we passed in a subdocument as another schema within an array:

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'
    }
)

As you can see, we're trying to access the specific assignment ID based on the passed in value in our post method from the Course Dashboard page, and then navigate to our generic/dynamically filled assignment page, but specifically the one that our AssignmentID specifies.

Our code is as follows:

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);
    });
});

This code below:

let input = req.params.assign;

stores the specific assignment's ID that we're looking for, yet the findOne (or find) method does not work properly, and returns the entire CS 212 course.

Any help would be appreciated, thank you!

CodePudding user response:

you can use $elematch for the above response in the project option. your query will look similar to this.

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

you have to add the fields you want in the response in the project field like I have added CourseName.

you can also do this using the $ projection operator, where the $ in a projection object field name represents the index of the field's first matching array element from the query.

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

in both the above answers it will return only the first element taht matches the query. if there are multiple object related to same assignment id you have to use aggregate

  • Related