繁体   English   中英

Firestore 事务顺序创建集合和更新文档

[英]Firestore transaction sequential creation of collections and updating of documents

环境: nodejsfirebase -adminfirestore

数据库结构(空格): 空间结构

数据库结构(用户): 在此处输入图片说明

创建新空间(示例):

// 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 中执行此代码,但是当我看到事务仅支持一次读取和多次更新时,这不适合我,因为我在执行代码期间获得了spaceId

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

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

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

实际上,您不需要交易,因为您没有阅读文档。

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


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

  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块中处理这种情况,因为知道没有提交任何写入。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM