如何创建需要找到目标文档的 firestore 事务

Mor*_*itz 5 android firebase google-cloud-firestore

我正在寻找一种创建 firestore 事务的方法,我从查询中找到一个文档,然后在事务中修改该文档。

沿着这些路线的东西(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)
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是该.limit(1)方法返回的查询不是 DocumentReference,这是事务接受的唯一类型。因此我的问题是,如何在 java/kotlin 中实现这样的事务?

我在这篇使用 admin sdk 的博客文章中看到了类似的内容:

  return trs.get(db.collection('rooms')
    .where('full', '==', false)
    .where('size', '==', size)
    .limit(1));
Run Code Online (Sandbox Code Playgroud)

5er*_*5er 5

经过调查,您似乎无法在 Kotlin/Java 中执行此操作,它不受支持。您必须创建云函数并执行类似以下操作:

exports.executeTransaction = functions.https.onRequest(async (req, res) => {

    const db = admin.firestore();

    const query = db
        .collection('collection')
        .where('name', '==', 'name')
        .limit(1);

    db.runTransaction(transaction => {
        return transaction
            .get(query)
            .then((querySnapshot) => {
                const gameDocSnapshot = querySnapshot.docs[0];
                const gameData = gameDocSnapshot.data();
                transaction.update(gameDocSnapshot.ref, { name: 'change' });
                return gameData;
            })
    })
        .then((gameData) => {
            res.send(gameData);
            console.log('Transaction successfully committed!', gameData);
        })
        .catch((error) => {
            res.send('Transaction failed:' + error);
            console.log('Transaction failed:', error);
        });
});
Run Code Online (Sandbox Code Playgroud)


cod*_*elt 4

我不了解 java/kotlin,但这是我在云函数中使用 TypeScript/JavaScript 实现的方法。

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);
    });
Run Code Online (Sandbox Code Playgroud)

规划 JavaScript 版本

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);
    });
Run Code Online (Sandbox Code Playgroud)

在这里找到我的答案: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);
    }
}
Run Code Online (Sandbox Code Playgroud)