【问题标题】:Get subcollection from firestore from same object - React typescript从同一对象的firestore获取子集合 - React typescript
【发布时间】:2021-01-30 18:41:37
【问题描述】:

我的界面是这样的:

界面反应:

export interface UserTask {
    assignee: String;
    date: String;
}


export interface TaskData {
    id: String;
    taskName: string;
    taskIcon: string;
    taskLog: UserTask[] 
}

Firebase 数据模型(结构):

- taskData (Main Collection)
    - taskIcon (fields)
    - taskName (fields)
    - taskLog (sub-collection) 
        - assignee  (fields)
        - date (fields)

React 代码获取 Firestore 数据:

import { firestore } from '../firebase';

...

function toTaskData(doc): TaskData {
    if (!doc.exists) {
        throw new Error("TaskData  not found!");
    } else {

        return { id: doc.id, ...doc.data()  } as TaskData;
    }
  }


  const getTaskData = async() => {
    const taskDataRef = firestore.collection('taskData');
    await taskDataRef.get().then(({docs}) => {
      setTaskData(docs.map(toTaskData));
    });
  }

来自 Firestore 的响应 JSON:

我只收到一个包含 taskNametaskIcon 数组而不是子集合 taskLog 的响应,我的问题是如何检索子集合或将其映射到 UserTask 数组?

【问题讨论】:

    标签: firebase google-cloud-firestore react-typescript


    【解决方案1】:

    Firestore 查询是:当您获取文档时,您不会获取其任何链接子集合中包含的数据。

    如果您想从其中一个子集合中获取 Firestore 文档及其所有文档,您需要执行两次提取:一次获取“父”文档,另一次获取子集合的所有文档。

    例如,您可以使用Promise.all() 执行以下操作:

    const taskDataRef = firestore.collection('taskData');
    const querySnapshot = await taskDataRef.get();
    
    const promises = querySnapshot.docs.map(doc => doc.ref.collection('taskLog').get());
    
    const querySnapshotsArray = Promise.all(promises);
    
    querySnapshotsArray.forEach(querySnapshot => {
       
       // Do something with the querySnapshot
       // e.g. querySnapshot.docs....
       // or querySnapshot.forEach(...)
    
    });
    

    如果您想将一个父级(taskData 文档)的数据与所有子级taskLog 文档组合在一起,请注意Promise.all() 返回一个解析为输入结果数组的 Promise promises 与输入数组的顺序相同。换句话说,querySnapshotsArraypromises 的顺序相同。


    请注意,这样做会导致从所有 taskLog 子集合中读取所有 taskData 文档和所有 taskLog 文档。以仅按需获取子集合的方式组织前端可能会更便宜(例如,如果用户单击按钮或展开部分等...)

    【讨论】:

    • 我知道你会建议创建一个名为 taskLogs 的数组而不是在子集合中创建它们吗?我理解阅读方面的内容,但我考虑稍后扩展该功能,可能会按日期和用户过滤搜索。
    • "您是否建议创建一个名为 taskLogs 的数组而不是在子集合中创建它们" => 这很难用可用的信息量来回答。这在很大程度上取决于您要从前端执行的查询。例如,您可能对按日期过滤特定 taskData 的 taskLogs 感兴趣 => 在这种情况下,子集合使 sebnse ... 另请注意,Firestore 文档的大小限制为 1 MiB => 如果您的 taskLogs 数组包含很多元素,你可能会达到极限。
    • 是的,这就是我采用这种方法的原因。如果问的不多,您可以扩展 querySnapshot 部分吗?我在querySnapshotsArray.forEach(doc => { 上遇到错误,可能会将文档限制为按日期排序的 5 个,因此查询不会读取很多文档?
    • querySnapshotsArray 不是DocumentSnapshots 的数组,而是querySnapshots 的数组。这就是为什么您需要循环两次:在querySnapshotsArray 上,然后在每个querySnapshot 上。
    • @CookieMonster 嗨,你有时间看答案吗?
    猜你喜欢
    • 1970-01-01
    • 2021-04-11
    • 2019-10-06
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-16
    • 2020-06-08
    相关资源
    最近更新 更多