Update or Insert object in array in MongoDB

Viewed 49

I have the following collection

{
    "_id" : ObjectId("57315ba4846dd82425ca2408"),
    "myarray" : [ 
        {
            userId : "8bc32153-2bea-4dd5-8487-3b65e3aa0869",
            Time:2022-09-20T04:44:46.000+00:00,
            point : 5
        },
        {
            userId : "5020db46-3b99-4c2d-8637-921d6abe8b26",
            Time:2022-09-20T04:44:49.000+00:00
            point : 2
        },        
     ]
}

These are my questions

I want to push into myarray if userId doesn’t exist, and if userid already exists then update time and point also I have to keep only 5 elements in the array if 6th element comes then I a have to sort the array based on Time and remove oldest time entry

what is the best way to do this in mongo using aggregation

FYI we are using Mongo 4.4

1 Answers

You can achieve this by using the aggregation pipeline update syntax, the strategy will be first to update the array (or insert a new element to it).

then if the size exceeds 5 we just filter it based on minimum value. like so:

const userObj = {point: 5, userId: "12345"};

db.collection.updateOne(
{ ...updateCondition },
[
  {
    $set: {
      myarray: {
        $cond: [
          {
            $in: [
              userObj.userId,
              {$ifNull: ["$myarray.userId", []]}
            ]
          },
          {
            $map: {
              input: "$myarray",
              in: {
                $cond: [
                  {
                    $eq: [
                      "$$this.userId",
                      userObj.userId
                    ]
                  },
                  {
                    $mergeObjects: [
                      "$$this",
                      {
                        Time: "$$NOW", // i used "now" time but you can swap this to your input
                        point: userObj.point
                      }
                    ]
                  },
                  "$$this"
                ]
              }
            }
          },
          {
            $concatArrays: [
              { $ifNull: ["$myarray", []] },
              [
                {
                  userId: userObj.userId,
                  point: userObj.point,
                  Time: "$$NOW"
                }
              ]
            ]
          }
        ]
      }
    }
  },
  {
    $set: {
      myarray: {
        $cond: [
          {
            $gt: [
              {
                $size: "$myarray"
              },
              5
            ]
          },
          {
            $filter: {
              input: "$myarray",
              cond: {
                $ne: [
                  "$$this.Time",
                  {
                    $min: "$myarray.Time"
                  }
                ]
              }
            }
          },
          "$myarray"
        ]
      }
    }
  }
])

Mongo Playground

Related