skip to Main Content

So assume I have a document as shown below:

{
    "_id" : ObjectId("6336d94e0330f5d48e44fb0f"),
    "systemId" : "5124301",
    "userId" : "9876543210",
    "tempId" : "123456da87sdafasdf",
    "updatedAt" : ISODate("2022-09-30T12:01:11.714+0000"),
    "receivedAt" : ISODate("2022-04-10T23:15:08.145+0000"),
}

Now I already have a tempId assigned to the doc and sometimes that field might expire and not exist inside the document. I wanted to know if I’m updating the document with a different receivedAt parameter or any other parameter and it does not have a tempId then only assign it a tempId else let the tempId be as it is.

What should be the query for this to get the updated docs as given by two examples?

Case 1: If tempId exists:

{
    "_id" : ObjectId("6336d94e0330f5d48e44fb0f"),
    "systemId" : "5124301",
    "userId" : "1234567890",
    "tempId" : "123456da87sdafasdf",
    "updatedAt" : ISODate("2022-09-30T12:01:11.714+0000"),
    "receivedAt" : ISODate("2022-04-10T23:15:08.145+0000"),
}

Case 2: If there is no tempId and it is generated as "13qeqrwrqwtqrfsdfweqr" in the above line and document needs to be updated with the generated tempId.

{
    "_id" : ObjectId("6336d94e0330f5d48e44fb0f"),
    "systemId" : "5124301",
    "userId" : "1234567890",
    "tempId" : "13qeqrwrqwtqrfsdfweqr",
    "updatedAt" : ISODate("2022-09-30T12:01:11.714+0000"),
    "receivedAt" : ISODate("2022-04-10T23:15:08.145+0000"),
}

The query would be something like this:

findOneAndUpdate({
    systemId: "5124301"
},
{
    {
        $set: {
            userId: "1234567890",
            receivedAt : ISODate("2022-04-10T23:15:08.145+0000"),
            tempId: {
                      $exists: then leave it as is, else update it with 13qeqrwrqwtqrfsdfweqr
            }
        }
    }
})

2

Answers


  1. Work with update with aggregation pipeline. Use $cond operator to check whether tempId is not equal ($ne) to undefined.

    If true, remain existing value $tempId.

    If false, assign value: "13qeqrwrqwtqrfsdfweqr".

    findOneAndUpdate({
      systemId: "5124301"
    },
    [
      {
        $set: {
          userId: "1234567890",
          receivedAt: ISODate("2022-04-10T23:15:08.145Z"),
          tempId: {
            $cond: {
              if: {
                $ne: [
                  "$tempId",
                  undefined
                ]
              },
              then: "$tempId",
              else: "13qeqrwrqwtqrfsdfweqr"
            }
          }
        }
      }
    ])
    

    Demo @ Mongo Playground

    Login or Signup to reply.
  2. I agree with @Yong Shun that using an aggregation pipeline to describe the transformation is the correct way to approach this. I offer an alternative syntax below just for general reference though both will satisfy the request as stated in the question perfectly fine.

    Mainly just leaving an additional answer as I’m curious about why this workflow around tempId exists. What do they represent, why can the coexist with userIds, and why is the application generating a new one for each of these write operations even if one may already exist? One thing that comes to mind is that you can construct your filter predicates for your update to include references to tempId (perhaps to only have the application generate a new one if needed). But more importantly I suspect that the entire workflow with tempId should be simplified, but that would require more specific knowledge about the application to say for sure.

    With respect to the alternative syntax, the tempId portion of the pipeline can be simplified to use the $ifNull operator:

    tempId: { $ifNull: [ "$tempId", "13qeqrwrqwtqrfsdfweqr" ]
    

    Full demo playground here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search