首页 > 解决方案 > 具有多个值的循环的 Firestore 查询

问题描述

我正在尝试使用字符串中保存的数据检索许多 Firestore 文档。这个想法是,对于数组中的每个值,我会使用 Firestore 查询来检索与该查询匹配的文档并将其推送到另一个数组。我在实现这一目标时遇到了一些问题。到目前为止,我已经尝试过:

exports.findMultipleItems = functions.https.onRequest((request, response) => {
    var list = ["item1", "item2", "item3", "item4"];

    var outputList = [];

    for (var i = 0; i < list.length; i++) {
        console.log("Current item: " + list[i]);
        let queryRef = db.collection("items").where('listedItems', 'array-contains', list[i]).get()
            .then(snapshot => {
                if (snapshot.empty) {
                    console.log('No matching documents.');
                }

                snapshot.forEach(doc => {
                    outputList.push(doc.data());
                });
                return;
            })
            .catch(err => {
                console.log('Error getting documents', err);
            });
    }

    response.send(JSON.stringify(outputList));

});

我不完全确定,但我认为问题之一是 for 循环在查询有机会完成之前完成。

Ps - 这是使用 Admin SDK 通过 Cloud Functions 运行的。

标签: javascriptfirebasegoogle-cloud-firestoregoogle-cloud-functions

解决方案


queryRef实际上不是参考。这是一个在你的 get/then/catch 完成后解决的承诺。您需要使用这些承诺来确定它们何时全部完成。只有在它们全部完成后才会填充数组,只有这样才能安全地使用该数组发送响应。

将所有的 Promise 收集到一个数组中,并使用 Promise.all() 获得一个新的 Promise,该 Promise 会在它们全部完成后解析:

exports.findMultipleItems = functions.https.onRequest((request, response) => {
    var list = ["item1", "item2", "item3", "item4"];

    var outputList = [];
    const promises = [];

    for (var i = 0; i < list.length; i++) {
        console.log("Current item: " + list[i]);
        let promise = db.collection("items").where('listedItems', 'array-contains', list[i]).get()
            .then(snapshot => {
                if (snapshot.empty) {
                    console.log('No matching documents.');
                }

                snapshot.forEach(doc => {
                    outputList.push(doc.data());
                });
                return;
            })
            .catch(err => {
                console.log('Error getting documents', err);
            });
        promises.push(promise);
    }

    Promise.all(promises).then(() => {
        response.send(JSON.stringify(outputList));
    }
    .catch(err => {
        response.status(500);
    })

});

您可能希望使用这些教程来更好地了解如何处理 Cloud Functions 中的 Promise:

https://firebase.google.com/docs/functions/video-series/


推荐阅读