【问题标题】:Decrement by a deleted document value Cloud Firestore按已删除文档值递减 Cloud Firestore
【发布时间】:2021-07-23 03:59:29
【问题描述】:

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

  • (任务已完成)用户可以设置每月预算(即 3,000 美元),该预算存储在年月集合中的“--currentBudget--”文档中。

  • (任务完成) 用户可以通过表单(标题、金额、类别、日期)添加费用,该表单存储在年月集合中的唯一文档中,然后数据按总支出和分类总支出在“--totalSpent--”中汇总。

  • (未完成) 用户可以删除会更新“--totalSpent--”中的值的费用。我将如何使用 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');
  });
}

【问题讨论】:

    标签: javascript firebase google-cloud-firestore


    【解决方案1】:

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

    您可以使用onCreate 和onDelete 事件触发器来更改总值。使用transactions 可以确保安全执行。

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

    这是您的数据库以及onCreate 和onDelete 触发器的基本示例:

    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 值的权限,所有更改都在后端自动完成。

    【讨论】:

    • 我遇到了交易问题,因为它们一直失败,读取 doc.data().totalSpending 时遇到问题,因为它是未定义的。它无法更新总支出。在我使用批量写入之前,它会创建“--totalSpent--”,但它无法使用事务读取。
    • 还是说未定义
    • Transaction failure: TypeError: Cannot read property 'totalSpending' of undefined. 我还手动设置了 firestore 数据库中仍未定义的值。
    猜你喜欢
    • 2021-10-16
    • 1970-01-01
    • 2018-08-02
    • 2018-03-22
    • 2020-12-11
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    相关资源
    最近更新 更多