javascript - 按已删除文档值递减 Cloud Firestore
问题描述
我正在创建一个费用跟踪器应用程序,其中:
(任务完成)用户可以设置每月预算(即 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');
});
}
解决方案
这非常适合Firebase Cloud Functions解决方案。
您可以使用onCreate
和onDelete
事件触发器来更改总值。随着transactions
您的使用,确保安全执行。
如果用户甚至可以更改现有费用中的值,您也可以使用onUpdate
触发器来处理这些用例。
这是您的数据库和onCreate
andonDelete
触发器的基本示例:
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
值的权利,所有更改都在后端自动完成。
推荐阅读
- javascript - 如何知道javascript中的CPU使用率?
- ruby-on-rails - graphql-ruby 基于连接的分页如何影响 ActiveRecord 查询?
- algorithm - 图上 DFS 的时间复杂度 (O(V+E)) 与矩阵上的 DFS (3^(M*N))
- phpstorm - JetBrains IDE - 如何在“Alt+Shift+Enter”之后删除选择
- gstreamer - 在 C 应用程序中使用合成器
- python-3.x - python网络爬虫,响应[403]
- javascript - 寻找交互式 SVG 地图脚本
- wso2 - 带有 JSON 输入的 WSO2 Smooks 中介
- javascript - 代码没有结果,初学者正在苦苦挣扎
- python - 如何获取 Excel 文件的元数据?