Ken
Ken

Reputation: 63

JavaScript Object: Cannot add new property to Object

I simply want to add another property that display course name when enrollments for a user are grabbed.

router.get('/enrollments/courses/me', auth, async (req,res)=>{
    user_id = req.user._id
    try{
        let Courses = await Enrollment.find({user_id})
        for(x in Courses){
            if(!Courses[x].course_id){
                throw new Error("No enrollments found for this student.")
            }
             courseName = await Course.findById(Courses[x].course_id)
             Courses[x].course_name = courseName.Course_Name
             console.log(Courses[x])
        }
        res.status(201).send(Courses)
    }catch(e){
        res.status(400).send(e)
    }
})

Example: Courses =

[
    {
        "_id": "607768e5e8105058546f658a",
        "user_id": "606e476107a74d49c4757c1f",
        "course_id": "60722e7392d7c6539c344a83",
        "createdAt": "2021-04-14T22:12:53.527Z",
        "updatedAt": "2021-04-14T22:12:53.527Z",
        "__v": 0
    },
    {
        "_id": "60777e7d6b2bff6040f46f58",
        "user_id": "606e476107a74d49c4757c1f",
        "course_id": "60722e8b92d7c6539c344a86",
        "createdAt": "2021-04-14T23:45:01.881Z",
        "updatedAt": "2021-04-14T23:45:01.881Z",
        "__v": 0
    },
    {
        "_id": "607787ec9f21525d644855a8",
        "user_id": "606e476107a74d49c4757c1f",
        "course_id": "60722e8392d7c6539c344a85",
        "createdAt": "2021-04-15T00:25:16.734Z",
        "updatedAt": "2021-04-15T00:25:16.734Z",
        "__v": 0
    },
    {
        "_id": "6078d78ea1ee7f05f89a3c17",
        "user_id": "606e476107a74d49c4757c1f",
        "course_id": "60722e6b92d7c6539c344a82",
        "createdAt": "2021-04-16T00:17:18.941Z",
        "updatedAt": "2021-04-16T00:17:18.941Z",
        "__v": 0
    }
]

courseName =

{
  "_id" : "60722e6b92d7c6539c344a82",
  "Course_Name" : "Course_1",
  "Description" : "This is my 1rst course",
  "__v" : 0
}

I loop through each enrollment and make another call to grab the Course name and add it to each object like so

Courses[x].course_name = courseName.Course_Name

The course name does not appear when I return Courses

I can do this :

Courses[x].course_id = courseName.Course_Name

and the course name appears for the course_id, but obviously I don't want to do that. This is how Ive added new properties to an Object before, why is this method not working?

Upvotes: 1

Views: 754

Answers (2)

Yogeshwar Chaudhari
Yogeshwar Chaudhari

Reputation: 503

As Christian & Patryk pointed out correctly,

"Courses" in your case will be an instance of mongoose.Document. You need to convert it into a native javascript object to be able to add new properties to it using -

Courses = Courses.toJSON();

or

Courses = Courses.toObject();

then you can add new property using,

Object.defineProperty(Courses[x], "course_name", {value : 'some value'});

or

Courses[x].course_name = courseName.Course_Name;

Upvotes: 1

Christian Fritz
Christian Fritz

Reputation: 21364

I believe this is due to the way mongoose converts Documents to json, which is implicit when you pass the Courses object to the res.send function. If you first make the courses plain objects, you should be able to get predictable results:

  ...
  let Courses = await Enrollment.find({user_id})
  Courses = Courses.map(x => x.toJSON())
  ...

Update:

As Patryk pointed out, it seems that Mongoose provides its own mechanism for doing just that: .lean. In that case this maybe be all you need:

  let Courses = await Enrollment.find({user_id}).lean()

Upvotes: 1

Related Questions