javascript - 如何为firebase admin realtime db编写批处理事务?
问题描述
有没有办法使用 admin sdk 在实时数据库中的不同字段上执行批处理事务?目前,我正在使用以下内容:
exports.function = functions.https.onCall((data, context) => {
var transactions = new Object();
transactions[0] = admin.database().ref('ref1/')
.transaction(currentCount => {
return (currentCount || 0) + 1;
}, (error, committed, dataSnapshot) => {...})
transactions[1] = admin.database().ref('ref2/')
.transaction(currentCount => {
return (currentCount || 0) + 1;
}, (error, committed, dataSnapshot) => {...})
return admin.database().ref().update(transactions)
// |^| error occurs right above '|^|', but i don't know why, i suspect it may have something to do with transactions object, and if so, what's the proper way to do batched transactions?
.then(result => {...})
.catch(error => {
console.error('error: ' + error)
})
}
但是每次调用此函数时,虽然事务确实作为批处理工作,但会引发以下错误:
Unhandled error TypeError: obj.hasOwnProperty is not a function
at each (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:541:17)
at validateFirebaseData (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1470:9)
at /srv/node_modules/@firebase/database/dist/index.node.cjs.js:1487:13
at each (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:542:13)
at validateFirebaseData (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1470:9)
at /srv/node_modules/@firebase/database/dist/index.node.cjs.js:1559:9
at each (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:542:13)
at validateFirebaseMergeDataArg (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1557:5)
at Reference.update (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:13695:9)
at admin.firestore.collection.doc.collection.doc.create.then.writeResult (/srv/index.js:447:43)
解决方案
您不能将一堆事务传递给update()
调用,这就是错误消息(诚然有些令人困惑)试图告诉您的内容。
Firebase 没有嵌套或批处理事务的概念。如果您需要在多个位置执行事务,则需要将其作为单个transaction
调用在所有这些位置之上的节点上运行。正如您可能猜到的那样,这种多位置事务的争用很快就会成为吞吐量限制,因此您需要考虑替代解决方案。
对于您的用例,我能想到的“最简单”的方法是用单个多位置更新替换两个事务,然后使用服务器端安全规则来验证操作。
有关如何执行类似操作的示例,请在此处查看我的答案:Firebase 数据库快速入门处理计数的方式是否安全?
使用这种方法,您可以防止大多数争用,因为多位置更新不需要读取-发送-检查整个顶级节点,而只需要您正在更新的较低级别节点。
您可能必须修改您的数据结构,甚至可能编写额外的数据,以允许这种方法。但作为回报,您将获得更具可扩展性的事务更新。
推荐阅读
- spring - Jackson反序列化JSON请求时如何注入bean?
- c# - 如何正确地将 ViewModel 中显示的数据与 Model 在使用 Collections 时提供的数据同步
- reactjs - 如何使用 SASS 模拟 Material UI 的“theme.mixins.toolbar”
- vue.js - 将构建时间戳注入 vue-cli 构建输出文件以验证使用 yarn 的部署
- android - kotlin simple_list_item_1 onclicklistener 不工作
- javascript - 如何自动将所有错误从 javascript 发送到 Sentry?
- azure - Azure Web Apps 上安装了哪些默认字体?
- c# - 在 C# 中使用 XOR 算法进行密码解密。程序因未知原因无法运行
- c - 在 C 代码中连接到 Oracle 时指定的 url 在哪里
- c# - DotNetBrowser 检查元素是否可见