正确更新交易中多个文档的方法

时间:2019-05-24 12:17:06

标签: node.js firebase transactions google-cloud-firestore

TL; DR 我应该使用Transaction.getAll()还是使用for循环并使用Transaction.get()

来一次更新文档

请考虑以下架构:

- someTopLevelCollection
   - accountId1
       - projects
       - tasks
       - users
  - accountId2
       - projects
       - tasks
       - users

每当在项目中创建一个项目/任务时,分别在task子集合中,在用户集合中的计数器都会更新,例如projectsCount和taskCount。

对用户的引用作为userId的数组保存在项目和任务中,如下所示:

  

注意:为简洁起见,其他字段已删除

项目/任务结构:

{
   "name": "someName",
   "status": "someStatus",
   "users": [
       "userId1",
       "userId2",
       ....
   ],
   ...
}

现在,我需要使用交易更新针对用户数组内所有userId的计数器。

方法1:

const accountId = context.params.accountId;
const userIds = snapshot.data().users;

userIds.forEach(userId => {

    const userDocRef = db.collection(someTopLevelCollection)
        .doc(accountId)
        .collection('users')
        .doc(userId);

    let transaction = db.runTransaction(transaction => {
        return transaction.get(userDocRef)
            .then(doc => {
                const snapshotData = doc.data();
                let newCounterValue = snapshotData[counterName] + 1;
                transaction.update(userDocRef, {counterName: newCounterValue});
                return Promise.resolve(`Incremented ${counterName} to ${newCounterValue}`);
            });

    }).then(result => {
        console.log('Transaction success!', result);
        return true;

    }).catch(err => {
        console.error('Transaction failure:', err);
        return false;
    });

});

方法2:

const accountId = context.params.accountId;
const userIds = snapshot.data().users;

let userDocRefs = [];
userIds.forEach(userId => {
    const userDocRef = db.collection(someTopLevelCollection)
        .doc(accountId)
        .collection('users')
        .doc(userId);
    userDocRefs.push(userDocRef)
});

let transaction = db.runTransaction(transaction => {
    return transaction.getAll(userDocRefs)
        .then(docs => {

            docs.forEach(doc => {
                const snapshotData = doc.data();
                let newCounterValue = snapshotData[counterName] + 1;
                transaction.update(doc.ref, {counterName: newCounterValue});
            });
            return Promise.resolve('Completed transaction successfully');

        });

}).then(result => {
    console.log('Transaction success!', result);
    return true;

}).catch(err => {
    console.error('Transaction failure:', err);
    return false;

});

以下是我的问题:

  1. getAll()低于外部而外部发生文档更改时 执行,将再次获取所有文档以进行维护 一致性。如果是这样,使用getAll()的用例是什么?
  2. 使用for循环和a逐一运行事务时 文档更改发生在当前文档的外部 在交易中进行了修改,是针对该交易重试的交易 文档

谢谢。

0 个答案:

没有答案
相关问题