1

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 Answer 1

0

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

Sign up to request clarification or add additional context in comments.

6 Comments

getting exception here $myarray.userId when there is no array in document and while inserting for the first time
You can solve it like this, by initializing the array as an empty [] if it doesn't exist.
Can't we handle that case in pipeline?
Yes, you mean like this?
mongoplayground.net/p/07YUVMoelcO getting this error when I try it fail to run update: write exception: write errors: [$in requires an array as a second argument, found: missing]
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.