Assuming a have a property “balance” of type Number.
I am adding/subtracting this property by using the inc
operator.
Is there a way to validate transactions so that queries that would result in the property being negative are rejected?
You do not need transaction to do that.
Start with document
{ _id : 5 , balance : 300 }
So rather than doing an update such as:
collection.updateOne( { _id : 5 } ,
{ $inc : { balance : -400} } )
that would result into a new balance of -100. You simply do:
collection.updateOne( { _id : 5 , balance : { $gte : 400 } } ,
{ $inc : { balance : -400} } )
With this query the update will not occur.
Above solution is fine. But what if I want to check multiple fields. eg
collection.updateOne( { _id : 5 } ,
{ $inc : { balance : -400, savings: 200, cost: 100} } )
the query should only update the values if they will be positive after updation. In above case, query should not update ‘balance’, but should increment ‘savings’ and ‘cost’
@Sudarshan_Dhatrak1 , you can apply the @steevej’s solution above to your new requirements:
db.balance.updateOne(
// filter params
{
_id: 5,
savings: { $gte: 400 }, // s1
costs: { $gte: 250 }, // c1
},
// update params
{
$inc: {
savings: -400, // s2
costs: -250 // c2
}
}
);
If you decrease values using $inc, make sure its absolute value in update params is not greater, then the value in filter params:
|s1| must be >= |s2]
|c1| must be >= |c2]
How to make condition that if it would go negative, then set it to be 0, else execute the $inc as it would otherwise?
Use $cond with an update with aggregation.
Hi, you can also use $max
operator like this:
db.collection.update({
_id: 1
},
[
{
"$set": {
"balance": {
"$max": [
{
"$subtract": [
"$balance",
400
]
},
0
]
}
}
}
])
So, if the balance after deduction is less than 0, it will be set to 0. Otherwise, it will be set to the amount after deduction.