4

So I have a nested array of objects in my MongoDB document and I would like to add a new object to the array only if a certain field (in this case, eventId) is unique. My question is very similar to this post, only I cannot seem to get that solution to work in my case.

Here is what the documents (UserModel) look like:

{
  "portal" : {
    "events" : [ 
      {
        "important" : false,
        "completed" : false,
        "_id" : ObjectId("5c0c2a93bb49c91ef8de0b21"),
        "eventId" : "5bec4a7361853025400ee9e9",
        "user_notes" : "My event note"
      },
      ...and so on
    ]
  }
}

And here is my (so far unsuccessful) Mongoose operation:

UserModel.findByIdAndUpdate(
  userId,
  { "portal.events.eventId": { $ne: req.body.eventId } },
  { $addToSet: { "portal.events": req.body } },
  { new: true }
);

Basically I am trying to use '$ne' to check if the field is unique, and then '$addToSet' (or '$push', I believe they are functionally equivalent in this case) to add the new object.

Could anyone point me in the right direction?

Cheers, Gabe

mickl
  • 48,568
  • 9
  • 60
  • 89
Gabor Szekely
  • 1,108
  • 5
  • 14
  • 1
    Why dont you use findOneAndUpdate and have the `$ne: req.body.eventId` inside your query? Also, findByIdAndUpdate only takes 3 parameters (if 4, the last one would be a callback), and you are sending 4 parameters – iagowp Dec 08 '18 at 21:45

2 Answers2

2

If you look into the documentation on your method you will see that the parameters passed are not in the proper order.

findByIdAndUpdate(id, update, options, callback)

I would use update instead and have your id and portal.events.eventId": { $ne: req.body.eventId } part of the initial filter followed by $addToSet: { "portal.events": req.body }

Something among these lines:

UserModel.update(
  { 
     "_id": mongoose.Types.ObjectId(userId), 
     "portal.events.eventId": { $ne: req.body.eventId }
  },
  { $addToSet: { "portal.events": req.body } },
  { new: true }
);
Akrion
  • 18,117
  • 1
  • 34
  • 54
1

You need to include your eventId check into condition part of your query. Because you're usig findByIdAndUpdate you can only pass single value matched against _id as a condition. Therefore you have to use findOneAndUpdate to specify custom filtering condition, try:

UserModel.findOneAndUpdate(
    { _id: userId, "portal.events.eventId": { $ne: req.body.eventId } },
    { $addToSet: { "portal.events": req.body } },
    { new: true }
);
mickl
  • 48,568
  • 9
  • 60
  • 89