如何在需要找到目标文档的地方创建Firestore交易 [英] How to create firestore transaction where target document needs to be found
问题描述
我正在寻找一种创建Firestore事务的方法,该方法是从查询中找到文档,然后在事务中修改此文档.
I am looking for a way to create a firestore transaction where i find a document from a query and then modify this document in a transaction.
类似的东西(科特琳):
Something along those lines (kotlin):
firestore.runTransaction { transaction ->
val snapshot = transaction.get(db.collection("document")
.whereEqualTo("someField", null)
.orderBy("creationDate", ASCENDING)
.limit(1L))
val myObject = snapshot.toObject(MyObject::class.java)
myObject.someFiled = "123"
transaction.set(snapshot.reference, myObject)
}
这里的问题是 .limit(1)
方法返回的查询不是DocumentReference,它是事务接受的唯一类型.因此,我的问题是,如何在java/kotlin中实现这种交易?
The problem here is that the query returned by the .limit(1)
method is not a DocumentReference, which is the only type the transaction accepts. Therefore my question is, how can such a transaction be achieved in java/kotlin?
I have seen something similar in this blog post using the admin sdk:
return trs.get(db.collection('rooms')
.where('full', '==', false)
.where('size', '==', size)
.limit(1));
推荐答案
我不了解java/kotlin,但这是我在Cloud Function中的TypeScript/JavaScript中实现的方法.
I don't know about java/kotlin but here is how I did it in TypeScript/JavaScript in a Cloud Function.
const beerTapIndex: number = parseInt(req.params.beerTapIndex);
const firestore: FirebaseFirestore.Firestore = admin.firestore();
firestore
.runTransaction((transaction: FirebaseFirestore.Transaction) => {
const query: FirebaseFirestore.Query = firestore
.collection('beerOnTap')
.where('tapIndexOrder', '==', beerTapIndex)
.limit(1);
return transaction
.get(query)
.then((snapshot: FirebaseFirestore.QuerySnapshot) => {
const beerTapDoc: FirebaseFirestore.QueryDocumentSnapshot = snapshot.docs[0];
const beerTapData: FirebaseFirestore.DocumentData = beerTapDoc.data();
const beerTapRef: FirebaseFirestore.DocumentReference = firestore
.collection('beerOnTap')
.doc(beerTapDoc.id);
transaction.update(beerTapRef, {enabled: !beerTapData.enabled});
return beerTapData;
})
})
.then((beerTapData: FirebaseFirestore.DocumentData) => {
console.log('Transaction successfully committed!', beerTapData);
})
.catch((error: Error) => {
console.log('Transaction failed:', error);
});
计划JavaScript版本
Plan JavaScript Version
const beerTapIndex = parseInt(req.params.beerTapIndex);
const firestore = admin.firestore();
firestore
.runTransaction((transaction) => {
const query = firestore
.collection('beerOnTap')
.where('tapIndexOrder', '==', beerTapIndex)
.limit(1);
return transaction
.get(query)
.then((snapshot) => {
const beerTapDoc = snapshot.docs[0];
const beerTapData = beerTapDoc.data();
const beerTapRef = firestore
.collection('beerOnTap')
.doc(beerTapDoc.id);
transaction.update(beerTapRef, {enabled: !beerTapData.enabled});
return beerTapData;
})
})
.then((beerTapData) => {
console.log('Transaction successfully committed!', beerTapData);
})
.catch((error) => {
console.log('Transaction failed:', error);
});
Found my answer here: https://medium.com/@feloy/building-a-multi-player-board-game-with-firebase-firestore-functions-part-1-17527c5716c5
异步/等待版本
private async _tapPouringStart(req: express.Request, res: express.Response): Promise<void> {
const beerTapIndex: number = parseInt(req.params.beerTapIndex);
const firestore: FirebaseFirestore.Firestore = admin.firestore();
try {
await firestore.runTransaction(async (transaction: FirebaseFirestore.Transaction) => {
const query: FirebaseFirestore.Query = firestore
.collection('beerOnTap')
.where('tapIndexOrder', '==', beerTapIndex)
.limit(1);
const snapshot: FirebaseFirestore.QuerySnapshot = await transaction.get(query);
const beerTapDoc: FirebaseFirestore.QueryDocumentSnapshot = snapshot.docs[0];
const beerTapData: FirebaseFirestore.DocumentData = beerTapDoc.data();
const beerTapRef: FirebaseFirestore.DocumentReference = firestore
.collection('beerOnTap')
.doc(beerTapDoc.id);
transaction.update(beerTapRef, {enabled: !beerTapData.enabled});
const beerTapModel = new BeerTapModel({
...beerTapData,
tapId: beerTapDoc.id,
});
res.send(beerTapModel);
});
} catch (error) {
res.send(error);
}
}
这篇关于如何在需要找到目标文档的地方创建Firestore交易的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!