[英]Firestore transaction sequential creation of collections and updating of documents
环境: 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 中执行此代码,但是当我看到事务仅支持一次读取和多次更新时,这不适合我,因为我在执行代码期间获得了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.