【问题标题】:how to write batched transactions for firebase admin realtime db?如何为 firebase admin realtime db 编写批处理事务?
【发布时间】:2020-02-08 03:43:52
【问题描述】:

有没有办法使用 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)

【问题讨论】:

  • transactions[0]transactions[1] 是什么 - 即 console.log 以查看内容 - 顺便说一下,transactions 应该是一个数组而不是一个对象吗?
  • @Jaromanda X, transactions[0] 和 transactions[1] 只是记录 [object Promise],我之前使用的是数组,但是在上传函数时收到警告,请改用 object
  • 所以它们是承诺...admin.database().ref().update 是否期望一个带有承诺的对象?
  • @Jaromanda X 不,文档没有说它专门接受承诺,但它确实接受以子路径作为键和值以及子作为值的对象,但我无法找到批处理事务上的任何内容,仅批处理写入。这是文档显示的有效内容:usersRef.update({ "alanisawesome/nickname": "Alan The Machine", "gracehop/nickname": "Amazing Grace" });,但这只是正常的批量写入

标签: javascript firebase firebase-realtime-database google-cloud-functions firebase-admin


【解决方案1】:

您不能将一堆事务传递给 update() 调用,这就是错误消息(诚然有些令人困惑)试图告诉您的内容。

Firebase 没有嵌套或批处理事务的概念。如果您需要在多个位置执行事务,则需要在所有这些位置之上的节点上将其作为单个 transaction 调用运行。正如您可能猜到的那样,这种多位置事务的争用很快就会成为吞吐量限制,因此您需要考虑替代解决方案。

对于您的用例,我能想到的“最简单”的方法是将两个事务替换为单个多位置更新,然后使用服务器端安全规则来验证操作。

有关如何执行类似操作的示例,请在此处查看我的答案:Is the way the Firebase database quickstart handles counts secure?

使用这种方法可以防止大部分争用,因为多位置更新不需要读取-发送-检查整个顶级节点,而只需要更新的较低级别节点。

您可能必须修改您的数据结构,甚至可能写入额外的数据,以允许这种方法。但作为回报,您将获得更具可扩展性的事务更新。

【讨论】:

  • 谢谢,刚刚使用Promise.all( [transaction1 here] , [transaction2 here] ),因为我还需要在函数中做一些其他的事情(创建firestore doc),我认为这里最可靠的方法是使用可调用函数,因为我需要写入两个数据库
猜你喜欢
  • 1970-01-01
  • 2021-11-29
  • 2020-07-18
  • 1970-01-01
  • 2019-11-14
  • 2019-05-10
  • 1970-01-01
  • 2016-12-04
  • 2021-02-11
相关资源
最近更新 更多