簡體   English   中英

Firebase v9 Firestore:一一添加2個文檔

[英]Firebase v9 Firestore: Add 2 documents one by one

首先,我想向 Firestore 添加一個文檔:

await setDoc(product, docData, {
    merge: true
});

一旦我 100% 確定文檔已成功寫入,我想添加/更新另一個文檔:

const products_array_snap = await getDoc(products_array);

if (products_array_snap.exists()) {
    await updateDoc(products_array, {
        products_array: arrayUnion(productSKU)
    });

    console.log("Product array exists:", products_array_snap.data());
} else {
    await setDoc(products_array, {
        products_array: arrayUnion(productSKU),
        products_default: productSKU
    });

    console.log("No product array!");
}

如何重寫此代碼以處理錯誤並確保兩個文檔正確設置在一起?

因為您的操作依賴於服務器的狀態(感謝products_default ),所以您需要將整個事情包裝在一個事務中 事務只會以全有或全無(原子)方式對數據庫進行更改,因此您可以保證如果它解決了,您的產品文檔和產品數組都將正確更新。

這些是以下塊使用的變量:

import { runTransaction, getFirestore, doc, collection } from "firebase/firestore";

const db = getFirestore();

const products_array_ref = doc(db, 'docIds/products');
const product_ref = doc(collection(db, 'products'));
const product_id = product_ref.id;
const product_data = { /* ... */ };

要使用runTransaction ,您需要傳入您正在使用的 Firestore 實例以及一個“更新函數”,該函數使用Transaction將更改runTransaction數據庫。 重要的是要記住,如果在您處理數據時服務器端的數據發生變化(例如添加/刪除了另一個產品),則可能會多次調用更新函數。

在這個函數中,你必須首先下拉你的事務所依賴的所有依賴項。 如果需要一次讀取多個文檔,可以使用Promise.all()並行抓取它們。 擁有所有依賴項后,您可以開始將要提交到服務器的更改排隊。 如果你從更新函數返回一個值,它會在它最終解析時從runTransaction傳遞出去。 您可以使用它來跟蹤嘗試了多少次,如果您自願中止交易,原始文檔是否存在等。如果由於爭用或其他問題而無法寫入交易, runTransaction將拒絕其 Promise適當的錯誤。

對於您的用例,您可以像這樣編寫邏輯:

const products_array_existed = await runTransaction(db, async (transaction) => {
  // dependencies
  const products_array_snap = await transaction.get(products_array_ref);

  // queue changes
  transaction.set(product_ref, product_data, { merge: true });
  if (products_array_snap.exists()) {
    transaction.update(
      products_array_ref,
      { products_array: arrayUnion(product_id) }
    );
  } else {
    transaction.set(
      products_array_ref,
      {
        products_array: arrayUnion(product_id),
        products_default: product_id
      },
      { merge: true }
    );
  }

  // set return value
  return products_array_snap.exists();
});

console.log(`Products array ${products_array_existed ? "already existed" : "was created"}.`);

或者

const products_array_existed = await runTransaction(db, async (transaction) => {
  // dependencies
  const products_array_snap = await transaction.get(products_array_ref);

  const products_array_change = {
    products_array: arrayUnion(product_id),
    ...(products_array_snap.exists() ? {} : { products_default: product_id })
  }

  // queue changes
  transaction.set(product_ref, product_data, { merge: true });
  transaction.set(products_array_ref, products_array_change, { merge: true });

  // set return value
  return products_array_snap.exists();
});

console.log(`Products array ${products_array_existed ? "already existed" : "was created"}.`);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM