Firestore获取子集合的所有文档

时间:2019-12-11 07:33:03

标签: node.js firebase google-cloud-firestore google-cloud-functions

我想创建一个函数,每2小时生成一次报告。到目前为止,我已将其固定以进行测试。我目前面临的问题是从transactions获取shops的所有数据,以便计算并生成reports集合中的记录。以下代码返回错误消息TypeError: Cannot read property 'map' of undefined

exports.generateReport = functions.pubsub.schedule('25 14 * * *').onRun(async (context) => {
    const shopSnapshot = await db.collection("shops").get();
    const shopDoc = shopSnapshot.docs.map(doc => doc.data());

    console.log(shopDoc);

    for(var i=0; i<shopDoc.length; i++){
        console.log(shopDoc[i].id);
        if(shopDoc[i].id !== "" || shopDoc[i].id !== null){
            console.log("Enter if:"+shopDoc[i].id);
            let transactionSnapshot = db.collection("shops").doc(shopDoc[i].id).collection("transactions").get();
            let transactionDoc = transactionSnapshot.docs.map(document => document.data());
            console.log(transactionDoc);
        }
    }

The image of firestore

2 个答案:

答案 0 :(得分:2)

在继续操作之前,您应该使用Promise.all()等待所有异步get()操作完成。

您可以执行以下操作:

exports.generateReport = functions.pubsub.schedule('25 14 * * *').onRun(async (context) => {
    const shopSnapshot = await db.collection("shops").get();
    const shopDoc = shopSnapshot.docs.map(doc => doc.data());

    console.log(shopDoc);

    const promises = [];

    for(var i=0; i<shopDoc.length; i++){
        console.log(shopDoc[i].id);

        if(shopDoc[i].id !== "" || shopDoc[i].id !== null){
            promises.push(db.collection("shops").doc(shopDoc[i].id).collection("transactions").get());
        }
    }

    const snapshotArrays = await Promise.all(promises);
    // snapshotArrays contains an array of arrays of QueryDocumentSnapshots 

    snapshotArrays.forEach(snapArray => {
        snapArray.forEach(snap => {
             // Proceed here with the snap (DocumentSnapshot)
             //E.g. sum up the amount or points values
           }))
        })
    }); 
    //Or call map on snapshotArrays.docs 

请注意,您可能需要在Transaction中的Cloud Function中进行此计算,以避免在计算时添加新的交易凭证。

Node.js的Admin SDK包括getAll()方法,该方法“从Firestore检索多个文档,并对所有返回的文档持有悲观的锁定。”

答案 1 :(得分:0)

get()是异步的,它返回一个Promise<DocumentSnapshot>,这意味着您可以使用then()来从Promise获取数据,例如:

 let transactionSnapshot = db.collection("shops").doc(shopDoc[i].id).collection("transactions").get().then((doc) => {
 let transactionDoc = transactionSnapshot.docs.map(document => document.data());
 console.log(transactionDoc);
});

https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference#get