具有查询问题的 Firestore 事务
Firestore transaction with query issue
我正在尝试 运行 需要从查询中获取数据的事务:
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);
});
对于我的申请,我需要 运行 查询才能完成我的交易。我收到错误:
Transaction failed: [FirebaseError: Function Transaction.get() requires its first argument to be a DocumentReference, but it was: a custom t object]
我了解交易需要文件参考。有解决办法吗?
transaction.get(query)
query
必须是 DocumentReference。所以你需要这样的东西:
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
}));
});
最接近的是用更高的限制做查询,然后在事务中,再次获取文档并再次检查所需的输入条件....
// 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
})
}
Transaction get
的第一个参数确实是文档引用,而不是查询。这是令人困惑的,因为 documentReference.get()
和 transaction.get(documentReference)
和 `query.get(),看起来和听起来都一样,但是事务只在单个文档上是原子的,而不是在查询的集合上, 甚至一个限制为 1.
我正在尝试 运行 需要从查询中获取数据的事务:
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);
});
对于我的申请,我需要 运行 查询才能完成我的交易。我收到错误:
Transaction failed: [FirebaseError: Function Transaction.get() requires its first argument to be a DocumentReference, but it was: a custom t object]
我了解交易需要文件参考。有解决办法吗?
transaction.get(query)
query
必须是 DocumentReference。所以你需要这样的东西:
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
}));
});
最接近的是用更高的限制做查询,然后在事务中,再次获取文档并再次检查所需的输入条件....
// 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
})
}
Transaction get
的第一个参数确实是文档引用,而不是查询。这是令人困惑的,因为 documentReference.get()
和 transaction.get(documentReference)
和 `query.get(),看起来和听起来都一样,但是事务只在单个文档上是原子的,而不是在查询的集合上, 甚至一个限制为 1.