'MongoDB Update array element (document with a key) if exists, else push

I have such a schema:

doc:
{
    //Some fields
    visits:
    [
        {
            userID: Int32
            time: Int64
        }
    ]

}

I want to first check if a specific userID exists, if not, push a document with that userID and system time, else just update time value. I know neither $push nor $addToSet are not able to do that. Also using $ with upsert:true doesn't work, because of official documentation advice which says DB will use $ as field name instead of operator when trying to upsert.

Please guide me about this. Thanks



Solution 1:[1]

You can use $addToSet to add an item to the array and $set to update an existing item in this array.

The following will add a new item to the array if the userID is not found in the array :

db.doc.update({
    visits: {
        "$not": {
            "$elemMatch": {
                "userID": 4
            }
        }
    }
}, {
    $addToSet: {
        visits: {
            "userID": 4,
            "time": 1482607614
        }
    }
}, { multi: true });

The following will update the subdocument array item if it matches the userId :

db.doc.update({ "visits.userID": 2 }, {
    $set: {
        "visits.$.time": 1482607614
    }
}, { multi: true });

Solution 2:[2]

const p = await Transaction.findOneAndUpdate(
            {
              _id: data.id,
              'products.id': { $nin: [product.id] },
            },
            {
              $inc: {
                actualCost: product.mrp,
              },
              $push: {
                products: { id: product.id },
              },
            },
            { new: true }
          );

or

db.collection.aggregate([
  {
    "$match": {
      "_id": 1
    }
  },
  {
    "$match": {
      "sizes.id": {
        "$nin": [
          7
        ]
      }
    }
  },
  {
    "$set": {
      "price": 20
    }
  }
])

https://mongoplayground.net/p/BguFa6E9Tra

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bertrand Martel
Solution 2 Rafiq