Hello, @Thomas_Plisson! Welcome to the community!
Due to the concurrency docs, write operations will be put in a queue and execute one by one on Mongo server. That means, it delete operation was issued after update operation, it will execute after update operation.
Since Mongo v4.2, update operations can use aggregation pipelines for updates. That means, that you can use $cond inside it:
db.test1.updateOne({ _id: ObjectId("5ed0d70c009dab1100a6209c")}, [
{
$set: {
name: {
$cond: {
if: {
// check if user has required permission
$in: [userPerm, '$permissions.write']
},
then: 1, // overwrite prop value
else: '$name', // return origin value
}
}
}
}
]);
In my example, I used updateOne() method, because it returns convenient for you situation result:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
This output means that 1 document matched by provided query, but it was not updated - either it already had the required value before update (it was modified long time ago or just now by another user) or because user has not enough permissions (due to the code logic).
You can achieve then same with .findOneAndUpdate() method and { returnNewDocumet: true } option by comparing your value with the one returned with method.
You can not differentiate those two cases (already same value, not enough permissions) using this approach, especially if there is a high chance that same value can be updated by multiple users.
The thing is, that you’re trying to assign too much work on 1 operation, such over-optimizations can lead to code complications. In your case, it would be totally OK to have 2 requests do database:
- fetch the document you want to update (1st request)
- check permissions (throw Error, if user permissions are not enough to update it)
- update the document, if fetched version had not actual state (2nd request)
You may end up with only 1 request anyway, if user has not enough permissions or the document already had desired value ![]()