3

I'm trying to decrement a field in a document and set a default value if it does not exist. My query below:

 usersCollection.findOneAndUpdate(
    {_id: id},
    {
        $inc: {quota: -1},
        $setOnInsert: {quota: 100}
    },
    {
        upsert: true,
        returnOriginal: false
    }
)

But this query gives the following error:

Updating the path 'quota' would create a conflict at 'quota'

If I don't use the $setOnInsert: {quota: 100} then it works but starts decrementing from 0 which I don't want. My goal is to set a default value (100) in this case and decrement on each query. Is this possible in 1 query ? I have searched around but didn't find something that could help.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Karan
  • 1,187
  • 2
  • 9
  • 16
  • The docs conveniently avoid this situation... – Sergio Tulentsev Mar 23 '19 at 15:21
  • @SergioTulentsev Are you saying it is not possible and discouraged ? – Karan Mar 23 '19 at 15:33
  • 1
    The basic premise is don't do it. Instead you really should separate the operations. A `bulkWrite()` is the most viable fix: `usersCollection.bulkWrite([{ updateOne: { filter: { _id: id }, update: { $inc: { quota: -1 } } }},{ updateOne: { filter: { _id: id }, update: { $setOnInsert: { quota: 100 }, upsert: true } }}])`. So basically **two** statements, where only the **second** attempts the *upsert* and the first only attempts to *modify*. – Neil Lunn Mar 24 '19 at 00:38

1 Answers1

0

I do not believe this is possible in a single query, as it contains an atomic operation ($inc) and contains two potential operations on the same field. (This would explain the 'quota' error message.)

You could use two different queries with the $exists operator to determine how the quota field should

adfontes
  • 304
  • 5
  • 12