7

This is the document I currently have:

{
    "_id": "",
    "title": "My Watchlist",
    "series": [{
        "seriesId": 1,
        "following": true,
        "seasons": []
    }, {
        "seriesId": 1,
        "following": false,
        "seasons": []
    }]
}

As you can see there are currently 2 objects with the seriesId 1, but with a different following boolean.

If the query matches with _id it should push the new object into series, if within the "series"-array an object with the same "seriesId" already exists it should change the fields within that object, instead of adding a new object.

I currently have the following query:

users.update(
    {"_id": req.body.userId},
    {
        "$push": {
            "series": {"seriesId": req.body.seriesId, "following": req.body.following}
        }
    }, (err, data) => {
        if (err)
            next(err);
    });

If I use $set it does not add the object if it didn't originaly exist yet, and as far as I know you cannot both use $push and $set? Can this be fixed in any way or do I have to rethink my Schema?

  • Possible duplicate of [Can mongo upsert array data?](http://stackoverflow.com/questions/13588342/can-mongo-upsert-array-data) – Mohammad Yusuf Dec 26 '16 at 13:47

1 Answers1

13

You can use two update query :

  • if _id is found and seriesId is not in the array, add the new item to the array :

    db.series.update({
        "_id": req.body.userId,
        "series": {
            "$not": {
                "$elemMatch": {
                    "seriesId": req.body.seriesId
                }
            }
        }
    }, {
        $addToSet: {
            series: {
                "seriesId": req.body.seriesId,
                "following": req.body.following,
                "seasons": []
            }
        }
    }, { multi: true });
    
  • if _id is found and seriesId is found in the array, update the array item :

    db.series.update({
        "_id": req.body.userId,
        "series.seriesId": req.body.seriesId
    }, {
        $set: {
            "series.$.following": req.body.following
        }
    }, { multi: true });
    
Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159
  • Since stuff can happen between the test and the actual update, this is unsafe design. For this design to be safe you would need some kind of transaction or compensation around the two operations. – HakonIngvaldsen May 16 '22 at 14:05