【问题标题】:Firebase firestore get data from collections documents and then subcollection documents in one arrayFirebase firestore 从集合文档中获取数据,然后在一个数组中获取子集合文档
【发布时间】:2020-08-15 12:33:51
【问题描述】:

我正在使用带有 express 的节点服务器并尝试从 firestore 数据库中获取数据。我的数据库结构如下

-Resource Collection
  - Documents with fields
     - comments subcollection
         - documents with fields
     - subresource subcollection
         - documents with fields

我正在尝试将上述所有数据映射到单个数组中,其中子资源和 cmets 嵌套在单个数组中。以下是我的代码。日志在一个数组中有正确的数据,但是当我发回响应时,它只显示 1 个资源,而且每次都是随机的。收集完所有数据后,promise.all 不应该阻止执行吗?我是否正确使用了承诺?

    response.set('Cache-Control','public, max-age=300, s-maxage=600');
    db.collection('Resources').get()
    .then(snapshot => {
        let Resources = snapshot.docs.map(doc => {
            var promises = [];
            let documentData = doc.data();
            documentData['id'] = doc.id;
            promises.push(db.collection('Resources').doc(documentData.id).collection('SubResources').get()
            .then(snapshot => {
                documentData['subresources'] = snapshot.docs.map(doc => {
                    let subResourceData = doc.data();
                    subResourceData['id'] = doc.id;
                    return subResourceData;   
                })
            }));
            promises.push(db.collection('Resources').doc(documentData.id).collection('Comments').get()
            .then(snapshot => {
                documentData['comments'] = snapshot.docs.map(doc => {
                    return doc.data();  
                })
            }));
            Promise.all(promises).then(function(){
                console.log(documentData);
                return response.json(documentData);            
            })
        })        

    })
    .catch(err => {
        console.log('Error getting documents', err);
    });
});

【问题讨论】:

  • 我不建议对数据库进行规范化,但恰恰相反,对它进行去异常化。
  • 记住firebase是一个faas
  • 我解释说,根据您的数据模型,您必须关注视图中信息的表示,无论数据是否冗余。因为firebase是一个faas。
  • 在“资源集合”中最关键的 cmets 和子资源数据在视图中表示。
  • 您的 Promise.all() 仅捕获获取子资源和 cmets 的承诺,而不是“资源”本身。所以对于哪个 Resource 它可以先完成获取子资源和 cmets,它会解析并返回数据。

标签: node.js firebase express promise google-cloud-firestore


【解决方案1】:

您的 Promise.all() 仅捕获获取子资源和 cmets 的承诺,而不是“资源”本身。所以对于哪个 Resource 可以先完成获取子资源和 cmets,它会解析并返回数据。

下面是对您的代码的轻微修改,以便它等待所有资源完成拉取 cmets/子资源,然后将它们作为数组返回。

response.set('Cache-Control','public, max-age=300, s-maxage=600');

db.collection('Resources').get()
.then(snapshot => {
    let ResourcePromises = snapshot.docs.map(doc => {
        var promises = [];
        let documentData = doc.data();
        documentData['id'] = doc.id;
        promises.push(db.collection('Resources').doc(documentData.id).collection('SubResources').get()
        .then(snapshot => {
            documentData['subresources'] = snapshot.docs.map(doc => {
                let subResourceData = doc.data();
                subResourceData['id'] = doc.id;
                return subResourceData;   
            })
        }));
        promises.push(db.collection('Resources').doc(documentData.id).collection('Comments').get()
        .then(snapshot => {
            documentData['comments'] = snapshot.docs.map(doc => {
                return doc.data();  
            })
        }));
        return Promise.all(promises).then(function(){
            //console.log(documentData);
            //return response.json(documentData);            
            return documentData;
        })
    });

    Promise.all(ResourcePromises).then(function(allResources) {
        return response.json(allResources);
    })

})
.catch(err => {
    console.log('Error getting documents', err);
});

您可能希望重构代码以分离函数,以便它们更具可读性。

【讨论】:

  • 我试图更新你提到的代码,但我从 promise.all(resourcepromises) 得到一个未定义的数组
  • 我已经更新了有错字和缺少返回的代码 - 您现在可以尝试一下。无论如何,我希望你的代码为什么返回随机单个文档的解释现在很清楚了。
  • 非常感谢。这行得通。我明白我做错了什么。非常感谢您详细解释这一点。
  • 我发现唯一可行的解​​决方案。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2021-09-11
  • 1970-01-01
  • 2020-09-05
  • 2018-04-09
  • 2018-04-04
  • 2018-07-01
相关资源
最近更新 更多