[英]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.