1

Basically I have the following schema.

{
    ...,
    description: {
        type: String,
        required: true,
        trim: true
    },
    tags: {
        type: [{
            type: String
        }]
    },
    lessons: [{
            name: String,
            description: String,
            video_path: String,
            comments: [
                {
                    user: mongoose.Schema.ObjectId,
                    content: String,
                    createdAt: {
                        type: Date, 
                        default: Date.now
                    }
                }
            ]
        }]
    ,
    createdAt: {
        type: Date
    }
}

I want to insert the following object to the comments array of a lesson object when the id of the lesson object is given.

{
  userId: "5e1b4790f7a3ca42accfeed3",
  content: "First comment"
}

The following is what I have tried. However it doesn't throw any error, but it's not inserting any comments to the DB also. Thanks for any helpful advice.

addComment: async (courseId, lessonId, userId, content, callback) => {
    Course.update(
      { _id: courseId, "lessons._id": lessonId },
      {
        $push: {
          comments: {
            user: userId,
            content: content
          }
        }
      },
      function(err, data) {
        if (err) {
          console.log(err);
          return callback(err, null);
        } else {
          console.log(data);
          return callback(null, data);
        }
      }
    );
  }

EDIT:

Collection data:

{ 
"_id" : ObjectId("5e1b4790f7a3ca42accfeed3"), 
"tags" : [ "mathematics", "beginner", "fundamentals" ], 
"name" : "Mathematics Toobox", 
"description" : "Mathematics includes the study of such topics as quantity (number theory), structure (algebra), space (geometry), and change (mathematical analysis).", 
"price" : 1500, 
"lessons" : [ 
    { 
      "_id" : ObjectId("5e1b48d9f7a3ca42accfeed4"), 
      "name" : "Welcome to the course", 
      "description" : "Welcome to Mathematics Toolbox course\n I’ll be your instructor for this course that runs for xx weeks ending on XXXXX.\n1. Access the technology tutorial located on your My Home page if you are new to the learning Hub, this online learning management system.", 
      "video_path" : "uploads\\1578846427336-Shakira - Hips Don't Lie ft. Wyclef Jean.mp4" 
    }, 
    { 
      "_id" : ObjectId("5e1e8f80cf166a2cb82b7a5e"), 
      "name" : "Number system", 
      "description" : "Baby just love me love me love me\nBaby just hold me hold me hold me\nOh love me ",
      "video_path" : "uploads\\1579061121969-Ellis - Migraine (feat. Anna Yvette) [NCS Release].mp4" 
    } 
], 
  "createdAt" : ISODate("2020-01-12T16:21:36.778Z"), 
  "__v" : 0, 
  "cover_path" : "uploads\\1578846099107-img_4.jpg" 
}
1
  • I couldn't use jsoneditor,so I put it in the question itself. Please have a look at it Commented Jan 16, 2020 at 17:24

2 Answers 2

1

There are a few problems in your schema.

I think you want to have an array of string tags.

Also you need to use ref property to make a reference to the User model.

So schema must be updated like this: (I assume that you used User in model creation.)

const mongoose = require("mongoose");

const courseSchema = new mongoose.Schema({
  description: {
    type: String,
    required: true,
    trim: true
  },
  tags: {
    type: [String]
  },
  lessons: [
    {
      name: String,
      description: String,
      video_path: String,
      comments: [
        {
          user: {
            type: mongoose.Schema.ObjectId,
            ref: "User"
          },
          content: String,
          createdAt: {
            type: Date,
            default: Date.now
          }
        }
      ]
    }
  ],
  createdAt: {
    type: Date
  }
});

module.exports = mongoose.model("Course", courseSchema);

Now you can use findByIdAndUpdate method with push and filtered positional operator $. to add a comment like this:

  Course.findByIdAndUpdate(
    { _id: courseId },
    {
      $push: { "lessons.$[lesson].comments": { user: userId, content } }
    },
    {
      arrayFilters: [{ "lesson._id": lessonId }],
      new: true
    },
    function(err, data) {
      if (err) {
        console.log(err);
         return callback(err, null);
      } else {
        console.log(data);
        return callback(null, data);
      }
    }
  );

Test:

Let's say you have an user with _id: 5e20954dc6e29d1b182761c9, and a course like this:

{
    "tags": [
        "tag1",
        "tag2"
    ],
    "_id": "5e209631a90e651e9c238df2",
    "description": "description1",
    "lessons": [
        {
            "comments": [],
            "_id": "5e209631a90e651e9c238df3",
            "name": "lesson1 name",
            "description": "lesson1 description",
            "video_path": "lesson1 video_path"
        }
    ],
}

When you send a comment with these values:

    courseId = "5e209631a90e651e9c238df2",
    lessonId = "5e209631a90e651e9c238df3",
    userId = "5e20954dc6e29d1b182761c9",
    content = "Comment Content"

The result will be:

{
    "_id" : ObjectId("5e209631a90e651e9c238df2"),
    "tags" : [
        "tag1",
        "tag2"
    ],
    "description" : "description1",
    "lessons" : [
        {
            "comments" : [
                {
                    "_id" : ObjectId("5e2099799edf132a08c2b997"),
                    "user" : ObjectId("5e20954dc6e29d1b182761c9"),
                    "content" : "Comment Content",
                    "createdAt" : ISODate("2020-01-16T20:12:25.243+03:00")
                }
            ],
            "_id" : ObjectId("5e209631a90e651e9c238df3"),
            "name" : "lesson1 name",
            "description" : "lesson1 description",
            "video_path" : "lesson1 video_path"
        }
    ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

@Pavindu did you used the schema code in my answer, please fully replace schema code with my schema, and try to send correct values. Arrange the values courseId, lessonId and userId to match your data.
0

This is what finally worked for me.

  const newData = {
        'lessons.$.comments': {
          user: userId,
          content: content
        }
      }

      Course.updateOne({_id: courseId,'lessons._id': lessonId}, {'$push': 
       newData 
    }, function(err,num) { 
      console.log(num)
      if(num.nModified > 0){
        callback(null,num)
      }
      else if(err){
        callback(err,null)
      }
    })
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.