【问题标题】:Firestore transaction sequential creation of collections and updating of documentsFirestore 事务顺序创建集合和更新文档
【发布时间】:2021-12-09 15:31:40
【问题描述】:

环境:nodejs、firebase-admin、firestore。

数据库结构(空格):

数据库结构(用户):

创建新空间(示例):

// init data
const userId = "someUserId";
// Create new space
const spaceRef = await db.collection("spaces").add({ name: "SomeName" });
// Get spaceId
spaceId = spaceRef.id;
// Get user Doc for upate their spaces
const userRef = await db.collection("users").doc(userId);
// Add "spaceId" to user spaces list
userRef.collection("spaces").doc(spaceId).set({ some: "data" });
// Create collection "members" in new space with "userId"
spaceRef.collection("members").doc(userId).set({role: "OWNER"})

问题:我想在单个runTransaction 中执行这段代码,但是我看到事务只支持一次性读取和多次更新,这不适合我,因为我得到了@ 987654327@我在代码执行过程中需要。

我为什么要使用事务:在我的数据结构中,需要创建空间和该空间的ID在用户身上的存在之间的关系。如果我们假设在执行这段代码的过程中发生了错误,例如创建了空间,但是这个空间没有添加到用户配置文件中,那么这将是我的数据库结构中的致命问题。

与其他数据库类似,事务解决了这个问题,但我不知道如何使用firestore。

也许您知道在这种情况下保护自己免受一致数据影响的更好方法?

【问题讨论】:

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


    【解决方案1】:

    实际上,您不需要 Transaction,因为您不是在阅读文档。

    使用db.collection("users").doc(userId);,您实际上不是在阅读文档,只是在“本地”调用doc() 方法来创建DocumentReference。此方法不是异步的,因此您不需要使用await。要阅读文档,您可以使用异步 get() 方法。


    因此,使用batched write,原子地将所有挂起的写入操作提交到数据库,就可以解决问题:

      const userId = 'someUserId';
      const userRef = db.collection('users').doc(userId);
    
      const spaceRef = firestore.collection('spaces').doc();
      const spaceId = spaceRef.id;
    
      const writeBatch = firestore.batch();
      writeBatch.set(spaceRef, { name: "SomeName" });
      writeBatch.set(userRef.collection("spaces").doc(spaceId), { some: "data" });
      writeBatch.set(spaceRef.collection("members").doc(userId), {role: "OWNER"});
    
      await writeBatch.commit();
    

    您应该将此代码包含在 try/catch 块中,如果批量提交失败,您将能够在 catch 块中处理这种情况,因为您知道没有提交任何写入。

    【讨论】:

    • hm,我误以为只有通过服务器响应操作.add ({name:" Some Name "}),才能得到新创建空间的ID。但事实证明,根据您的示例判断,.doc () 函数为之前准备了一个随机的id,根本没有请求服务器,并且在创建它时已经使用它。 .doc () 函数没有按我的预期工作:) 谢谢。
    • "doc() 函数为之前准备了一个随机 id,无需向服务器请求" => 就是这样!
    猜你喜欢
    • 2020-08-25
    • 2021-05-12
    • 2019-07-20
    • 2020-12-17
    • 2020-10-16
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 2019-12-30
    相关资源
    最近更新 更多