Tautvydas Būda
Tautvydas Būda

Reputation: 214

mongodb/mongoose addToSet adds object to array with the same id

So the issue that I'm having is that I want to like user comment only one time, currently im using addToSet operator, since by definition it doesn't add value if that value is already present.

But in my case it adds, probably because I am adding object instead of value and when I add mongo generates _id?

This is my event model:

  creator: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  },
  comments: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: 'User'
      },
      text: {
        type: String,
        required: true
      },
      likes: [
        {
          user: {
            type: Schema.Types.ObjectId,
            ref: 'User'
          }
        }
      ]
    }
  ]
}

And this is my addLike function:

commentLike: async (req, res) => {
    console.log('working', req.params.id, req.params.idas, req.params.commentID);
    Events.findOneAndUpdate(
      { _id: req.params.idas, comments: { $elemMatch: { _id: req.params.commentID } } },
      { $addToSet: { 'comments.$.likes': { user: req.params.id } } },
      (result) => {
        res.json(result);
      }
    );
  }

My likes array looks like this when I add like:

        "likes" : [
            {
                "user" : ObjectId("5b53442c1f09f525441dac31"), 
                "_id" : ObjectId("5b54a5263e65324504035eac")
            }, 
            {
                "user" : ObjectId("5b4b4725a3a5583ba8f8d513"), 
                "_id" : ObjectId("5b54a5bb3e65324504035eb0")
            },
          ]

Upvotes: 1

Views: 3977

Answers (2)

Clayton Gulick
Clayton Gulick

Reputation: 10375

Another option is to change your schema definition to add "_id: false" to prevent the _id field from being generated for subdocs in the array.

In this case, $addToSet will work as you expect, even with nested subdocs as long as your doc exactly matches.

comments: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: 'User'
      },
      text: {
        type: String,
        required: true
      },
      likes: [
        {
          _id: false, //add this
          user: {
            type: Schema.Types.ObjectId,
            ref: 'User'
          }
        }
      ]
    }
  ]

Upvotes: 1

Ashh
Ashh

Reputation: 46491

You can follow this

db.collection.update(
  { "_id": req.params.idas, "comments": { "$elemMatch": { "_id": req.params.commentID, "likes.user": { "$ne": req.params.id } } } }, 
  { "$push": { "comments.$.likes": { "user": req.params.id } } }
})

And if you just started with your project then you should follow JohnnyHK opinion and make your array some thing like this to make $addToSet workable

likes: [{ type: Schema.Types.ObjectId, ref: 'User' }]

Upvotes: 3

Related Questions