Reputation: 1414
In my very simple app, I keep a running aggregate each time a new transaction is added/changed/deleted. I realised that I could simply loop through each transaction every time but this seems expensive. As such, I switch on the event type and apply a different logic depending if its a create/update/delete.
exports.aggregateTransactions = functions.firestore
.document('budgets/{budgetId}/transactions/{transactionId}')
.onWrite(async (change, context) => {
adjustment = 0;
if(change.after.data == undefined){
adjustment = -1 * change.before.data().amount;
}
if(change.before.data && change.after.data){
adjustment = change.after.data().amount - change.before.data().amount;
}
if(!change.before.data && change.after.data){
adjustment = change.after.data().amount;
}
const budgetRef = db.collection('budgets').doc(context.params.budgetId);
await db.runTransaction(async (transaction) => {
const budgetDoc = await transaction.get(budgetRef);
const newBalance = budgetDoc.data().balance + adjustment;
transaction.update(budgetRef, {
balance: newBalance
});
});
});
This feels like a lot of code each time just to work out what kind of event is happening. Is there a better way to handle this?
Upvotes: 0
Views: 52
Reputation: 599736
Most of the code looks fine to me. I'd just use a FieldValue.increment()
operation for updating the budget, instead of a transaction:
const budgetRef = db.collection('budgets').doc(context.params.budgetId);
budgetRef.update({ balance: admin.firestore.FieldValue.increment(adjustment) });
For more on this operation, see the documentation on incrementing a numeric value.
Upvotes: 1