I'm New to firestore. I need a little help.
I got a function, that updates the amount of "stock shares". its a "sell" function, so the amount can only go down.
The problem is. I don't wanna go below 0.
So I wanna get the PREVIOUS amount of shares. before I update to the new amount. So I can make sure I don't go below 0.
There are 2 ways to do this. 1 is by using firestore rules, 2 is by getting the Prev amount like i said.
Can you guys help me get the Prev amount before the UPDATE stage? code:
function sellStock(){
db.collection("Stocks")
.where("ticker", "==", props.name)
.get()
.then((querySnapshot) => {
if(!querySnapshot.empty){
querySnapshot.forEach(function(doc){
db.collection("myStocks")
.doc(doc.id)
.update({
shares: doc.data().shares - amount
})
"shares" will be the prev amount. "amount" will be the amount of shares we wanna sell.
CodePudding user response:
Try this way:
.update({
shares: (doc.data().shares - amount) >= 0 ? (doc.data().shares - amount) : 0
})
CodePudding user response:
Normally, in such a case you should use a Transaction: "if a transaction reads documents and another client modifies any of those documents, Cloud Firestore retries the transaction".
However, since you want to update several documents, returned by a query, you cannot use a Transaction of one of the mobile/web SDKs (e.g. iOS, Android, Web/JavaScript), because the mobile/web SDKs use optimistic concurrency controls to resolve data contention.
What you can do is to use one of the Admin SDKs, like the Node.js one, since it uses pessimistic concurrency controls and therefore offers the possibility to run a Transaction on a query (see that you can pass a query to the get()
method). So you could do that in a Callable Cloud Function, with the following code:
exports.updateTickers = functions.https.onCall((data, context) => {
// get the value of the filter (i.e. props.name) via the data Object
const filter = data.filter;
const amount = data.amount;
const db = admin.firestore();
return db.runTransaction(transaction => {
let queryRef = db.collection("Stocks").where("ticker", "==", filter);
return transaction.get(queryRef)
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const currentValue = doc.get('amount');
if (currentValue - amount > 0) (
transaction.update(doc.ref, { likes: currentValue - amount })
)
});
});
})
.then(() => {
return { result: "Amounts update successful" }
})
});