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

时间:2017-12-06 16:07:05

标签: 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)
}

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

我在this blog post使用admin sdk:

看到了类似的内容
  return trs.get(db.collection('rooms')
    .where('full', '==', false)
    .where('size', '==', size)
    .limit(1));

2 个答案:

答案 0 :(得分:0)

我不知道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);
    });

规划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);
    });

在这里找到我的答案: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);
    }
}

答案 1 :(得分:0)

经过调查,您似乎无法在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);
        });
});