0

I have a document like this

    {
      "_id": ObjectId("626f942bb092f78afd9dad9d"),
      "item_id": "external _id222",
      "metadata": {
        "item_name": "abc",
        "quantity": 123,
        "state": null
      },
    }

What I would like to do is, $inc i.e. increment the count of quantity and then update the state to SOLD, if quantity equals 124. I can do this by 2 queries, update quantity, do an if-else check and then update state. Is there a way to do this in one single query by update()? (preferably without aggregation)

ray
  • 11,310
  • 7
  • 18
  • 42
Matt_crud
  • 85
  • 1
  • 6

2 Answers2

0

You can do this way

  1. Check if quantity is 123
  2. Then increment quantity and set state to SOLD

playground

db.collection.update({
  "metadata.quantity": 123
},
{
  "$inc": {
    "metadata.quantity": 1
  },
  "$set": {
    "metadata.state": "SOLD"
  }
},
{
  "multi": false,
  "upsert": false
})

Here, the trick is that you need to check the value which is before $inc operation.

Gibbs
  • 21,904
  • 13
  • 74
  • 138
  • the quantity part doesn't need to be the match condition in my case. And i was looking for something like a waterfall way, like update quantity, check if its equal to certain value, if true then update state. – Matt_crud May 20 '22 at 13:19
  • Then, @ray's answer will help you – Gibbs May 20 '22 at 13:20
0

With MongoDB v4.2+, you can do this with a single update with an aggregation pipeline to achieve atomic behaviour. Use $add to do the increment and $cond to check for quantity = 123

db.collection.update({
  "item_id": "external _id222"
},
[
  {
    $set: {
      "metadata.quantity": {
        $add: [
          "$metadata.quantity",
          1
        ]
      }
    }
  },
  {
    $set: {
      "metadata.state": {
        $cond: {
          if: {
            $eq: [
              "$metadata.quantity",
              124
            ]
          },
          then: "SOLID",
          else: "$metadata.state"
        }
      }
    }
  }
],
{
  multi: true
})

Here is the Mongo playground for your reference.

ray
  • 11,310
  • 7
  • 18
  • 42
  • Did I misunderstand the question :O ? – Gibbs May 20 '22 at 13:07
  • @Gibbs I am not sure. Actually I just come into [another old question](https://stackoverflow.com/questions/24280144/mongodb-field-increment-with-max-condition-in-update-statement/72312540#72312540) which has a similar scenario but OP of that question actually want to select by some other criteria to perform the update, so I just post my similar answer here to see if it can helps OP here. – ray May 20 '22 at 13:11
  • 1
    ok, I got your point. let's see what Matt thinks. – Gibbs May 20 '22 at 13:19
  • Can't it execute in a waterfall method? In this script, the value increments to 124 but the condition doesn't work, it works in the next iteration when quantity becomes 125. According to my question, `state` should update when `quantity` becomes 124 – Matt_crud May 20 '22 at 13:26
  • @Matt_crud You can break the aggregation into 2 stages to achieve the "waterfall" behaviour. Updated the answer to demonstrate that. – ray May 20 '22 at 13:37