javascript 存在查询问题的Firestore事务

dsekswqp  于 2023-02-28  发布在  Java
关注(0)|答案(2)|浏览(116)

我正在尝试运行需要从查询中获取数据的事务:

firestore
          .runTransaction((transaction) => {
            const query = firestore
              .collection("Lottories")
              .doc("R3DYubrqFbbVfQNjYXfh")
              .collection("sets")
              .where("isAvailable", "==", false)
              .limit(1);
            return transaction.get(query).then((snapshot) => {
              const ticketDoc = snapshot.docs[0];
              const ticketDocData = ticketDoc.data();
              const lottoUpdate = firestore
                .collection("Lottories")
                .doc("R3DYubrqFbbVfQNjYXfh")
                .collection("sets")
                .doc(ticketDoc.id);
              const ticketUpdate = firestore
                .collection("UserLotto")
                .doc(userId)
                .collection("tickets")
                .doc("abc");
              const countUpdate = firestore
                .collection("UserData")
                .doc(userId);
              transaction.update(lottoUpdate, { isAvailable: true });
              transaction.update(countUpdate, {
                ticketCount: ticketCount - 2,
              });
              transaction.set(ticketUpdate, {
                ticketId: ticketDoc.id,
                lottoId: "abc",
                claimed: false,
              });

              return ticketDocData;
            });
          })
          .then((ticketDocData) => {
            console.log(
              "Transaction successfully committed!",
              ticketDocData
            );
            setPopScreen("ticketPurchased");
          })
          .catch((error) => {
            console.log("Transaction failed:", error);
          });

对于我的应用程序,我需要运行一个查询,以完成我的事务。我得到的错误:
交易失败:[Firebase错误:函数Transaction.get()要求它的第一个参数是DocumentReference,但它是:自定义测试对象]
我知道事务处理需要文档参考。是否有解决方法?

zf9nrax1

zf9nrax11#

最接近的等效方法是使用更高的限制进行查询,然后在事务中再次获取文档并再次检查所需的输入条件......

// this will do the OP sets/updates, but *doesn't* assume the input
// doc meets the required condition (isAvailable==true)
// return a bool indicating success
function reserveDoc(lottoDoc) {
  return firestore.runTransaction(transaction => {
    return transaction.get(lottoDoc.ref).then(ticketDoc => {
      // important, check the original condition again here
      if (ticketDoc.data().isAvailable) {
        // OP code to set/update goes here
        return true
      } else {
        return false
      }
    })
  })
}

// try a transaction on the first doc in the array.  return if successful
// otherwise, try recursively on the remainder of the array
// return a bool indicating success
function reserveOneOf(lottoDocs) {
  if (lottoDocs.length === 0) return false
  return reserveDoc(lottoDocs[0]).then(success => {
    // did it work?  if not, try another doc
    return success ? success : reserveOneOf(lottoDocs.slice(1))
  })
}

function originalOPFunction() {
  const query = firestore
    .collection("Lottories")
    .doc("R3DYubrqFbbVfQNjYXfh")
    .collection("sets")
    .where("isAvailable", "==", true)  // note, I assume the OP query had a typo, checking for false
    .limit(10);
  return query.get().then(snapshot => {
    return reserveOneOf(snapshot.docs)
  }).then(success => {
    // if !success here, the app must deal with NO docs currently meeting the criterion
    // the OP needed to handle this circumstance anyway (if the limit(1) query returned no docs
  })
}

事务get的第一个参数实际上是一个文档引用,而不是查询。这是令人困惑的,因为documentReference.get()transaction.get(documentReference)query.get()看起来和听起来都差不多,但事务只是单个文档上的原子,而不是查询中的集合上的原子,即使是限制为1的集合。

ibrsph3r

ibrsph3r2#

transaction.get(query)query必须是一个文档引用。因此,您需要类似以下的内容:

db.collection("Lottories/R3DYubrqFbbVfQNjYXfh/sets")
    .where("isAvailable", "==", false)
    .limit(1)
    .get()
    .then((docs) => {
      db.runTransaction((transaction) => transaction.get(docs[0]).then((doc) => {
        if (doc.exists) //do something
      }));
    });

相关问题