首页 > 解决方案 > 按已删除文档值递减 Cloud Firestore

问题描述

我正在创建一个费用跟踪器应用程序,其中:

Firestore 控制台 https://i.stack.imgur.com/eKTUg.jpg

/* ADD EXPENSE */
function addExpense(user) {
  // DOM Form Selectors
  const expenseForm = document.getElementById('expense-form');
  const expenseTitle = document.getElementById('expense-title');
  const expenseAmount = document.getElementById('expense-amount');
  const expenseCategory = document.getElementById('expense-category');
  const expenseDate = document.getElementById('expense-date');

  // Submit Event
  expenseForm.addEventListener('submit', e => {
    e.preventDefault();

    // Database Reference
    const increment = firebase.firestore.FieldValue.increment(expenseAmount.value);
    const expenseRef = db.collection('users').doc(user.uid).collection(expenseDate.value).doc();
    const totalSpent = db.collection('users').doc(user.uid).collection(expenseDate.value).doc('--totalSpent--');

    // Database Batch Write
    const batch = db.batch();

    // Creates Unqiue Expense Document
    batch.set(expenseRef, { title: expenseTitle.value, amount: expenseAmount.value, category: expenseCategory.value, date: expenseDate.value });

    // Updates totalSpending
    batch.set(totalSpent, { totalSpending: increment }, { merge: true });
    //Updates totalSpending by category
    batch.set(totalSpent, { [expenseCategory.value]: increment }, { merge: true });
    batch.commit();

    // Reset Form
    expenseForm.reset();
    modal[1].classList.add('hidden');
    overlay.classList.add('hidden');
  });
}

标签: javascriptfirebasegoogle-cloud-firestore

解决方案


这非常适合Firebase Cloud Functions解决方案。

您可以使用onCreateonDelete事件触发器来更改总值。随着transactions您的使用,确保安全执行。

如果用户甚至可以更改现有费用中的值,您也可以使用onUpdate触发器来处理这些用例。

这是您的数据库和onCreateandonDelete触发器的基本示例:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

exports = module.exports = functions.firestore
  .document("/users/{userUid}/{year_month}/{expenseUid}")
  .onCreate(async (eventSnapshot, context) => {
    const { userUid, expenseUid } = context.params;
    const expenseData = eventSnapshot.data();
    const { spending = 0 } = expenseData;

    try {
      await admin.firestore().runTransaction(async (t) => {
        const totalRef = admin
          .firestore()
          .doc("/users/{userUid}/{year_month}/--totalSpend--");
        const doc = await t.get(totalRef);

        const newTotalSpending = doc.data().totalSpending || 0 + spending;
        t.update(totalRef, { totalSpending: newTotalSpending });
      });

      console.log("Transaction success!");
    } catch (e) {
      console.log("Transaction failure:", e);
    }
  });

exports = module.exports = functions.firestore
  .document("/users/{userUid}/{year_month}/{expenseUid}")
  .onDelete(async (eventSnapshot, context) => {
    const { userUid, expenseUid } = context.params;
    const expenseData = eventSnapshot.data();
    const { spending = 0 } = expenseData;

    try {
      await admin.firestore().runTransaction(async (t) => {
        const totalRef = admin
          .firestore()
          .doc("/users/{userUid}/{year_month}/--totalSpend--");
        const doc = await t.get(totalRef);

        const newTotalSpending = doc.data().totalSpending || 0 - spending;
        t.update(totalRef, { totalSpending: newTotalSpending });
      });

      console.log("Transaction success!");
    } catch (e) {
      console.log("Transaction failure:", e);
    }
  });

使用云功能的主要好处是您无需授予用户编辑total值的权利,所有更改都在后端自动完成。


推荐阅读