NickP
NickP

Reputation: 1414

onWrite Aggregate Function

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

Answers (1)

Frank van Puffelen
Frank van Puffelen

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

Related Questions