0
                execTransaction(session => {
                    return async () => {
                        await db.collection('table1').updateOne({ username: username }, { $push: { apps: client_id } }, { session });
                        await db.collection('table2').insertOne({ data: data }, { session });
                    };
                }, data => {
                    console.log(data); //data.result.ok = 1
                 
                });

I use withTransaction in nodejs to run transaction.

When I run the transaction correctly, data.result.ok = 1

But when I use no exist username run updateOne, the result is still 1.

How to verify the result?

oscxc
  • 1
  • 2
  • 1
    You will always get result as Ok. To verify the number of document updated check for the property "modifiedCount" – Deepak Singh Nov 21 '21 at 12:34
  • There is no 'modifiedCount' and other useful property in the return data. @Deepak Singh – oscxc Nov 21 '21 at 12:54
  • Not updating the document in the collection is _not_ a failure of the operation (and the transaction). It only means that a query is performed, there was no matches and hence no update happened. You can build your own logic - that when the update didn't happen then rollback / abort the transaction. – prasad_ Nov 22 '21 at 09:05

1 Answers1

1

insertOne should return an Object like this if successful

{
  acknowledged: true,
  insertId: <object OjectId> // or the _id you specified
}

updateOne should return an Object like this if successful

{
  acknowledged: true,
  modifiedCount: 1, // or 0 if upserted
  upsertedId: null, // or an <object OjectId>
  upsertedCount: 0, // or 1 if upserted
  matchedCount: 1 // or 0 if upserted
}

Now, updateOne only updates the first document that matched the query. If no document matched the query, it would simply update no document and throw no errors. You would get an object like this if that happens,

{
  acknowledged: true,
  modifiedCount: 0,
  upsertedId: null,
  upsertedCount: 0,
  matchedCount: 0
}

So, checking data.result.ok would tell you nothing in that scenario. You have to manually check each method call if you want to something like that. In your case, maybe do something like this?

execTransaction(session => {
    return async () => {
      await Promise.all([
        db.collection('table1').updateOne({ username: username }, { $push: { apps: client_id } }, { session }),
        db.collection('table2').insertOne({ data: data }, { session })
      ])
    };
  }, data => {
    if (data[0].matchedCount === 0) {
      // do error handling ?
    }
  }
)

Or, if you want to know if all the CRUD operations succeeded as the title suggests, maybe this?

(await Promise.all([a list of all insertOne and updateOne operations... ])
  .every(obj => obj && obj.acknowledged && (obj.insertId || obj.modifiedCount || obj.upsertedCount))
// this checks if all the properties are non zero
// thus if It's true, everything succeed

But again I would suggest you to do error handling separately for each operation when needed.

touhidurrr
  • 318
  • 2
  • 11