【发布时间】:2020-04-16 01:46:36
【问题描述】:
TL;DR 获取少量文档需要很长时间
场景:
我为每个帐户都有一个集合,每个帐户都包含一个projects子集合和tasks子集合。 tasks 子集合中的每个文档还可以包含checkLists子集合中的清单
注意:
- 项目可以包含任务,而任务又可以包含清单。
- 任务可以独立创建,即;它不一定是项目的一部分。
- 项目和任务都是顶级子集合,checkLists 子集合嵌套在每个任务中。
插图:
someTopLevelDB
|
|____ accountId1
| |______projects
| | |_______ projectId1
| |
| |______tasks
| |________taskId1 (belongs to projectId1)
| | |
| | |________checkLists
| | |
| | |_____checkListId1
| |
| |________taskId2 (standalone)
用例: 当用户单击重复项目(从 UI)时,我必须创建整个项目的副本,即;所有任务、清单等。
代码: 这样做的过程很慢,当我分析代码时,这个 sn-p 需要很长时间才能执行。 sn-p 获取所有任务及其清单
let db = admin.firestore();
function getTasks(accountId) {
return db.collection('someTopLevelDB')
.doc(accountId)
.collection('tasks')
.where('deleted', '==', false)
.get();
}
function getCheckLists(accountId, taskId) {
return db.collection('someTopLevelDB')
.doc(accountId)
.collection('tasks')
.doc(taskId)
.collection('checkLists')
.where('deleted', '==', false)
.get();
}
async function getTasksAndCheckLists(accountId) {
try {
let records = { tasks: [], checkLists: [] };
// prepare tasks details
const tasks = await getTasks(accountId);
const tasksQueryDocumentSnapshot = tasks.docs;
for (let taskDocumentSnapshot of tasksQueryDocumentSnapshot) {
const taskId = taskDocumentSnapshot.id;
const taskData = taskDocumentSnapshot.data();
const taskDetails = {
id: taskId,
...taskData
};
records.tasks.push(taskDetails);
// prepare check list details
checkListQueryDocumentSnapshot = (await getCheckLists(accountId, taskId)).docs;
for (let checkListDocumentSnapshot of checkListQueryDocumentSnapshot) {
const checkListId = checkListDocumentSnapshot.id;
const checkListData = checkListDocumentSnapshot.data();
const checkListDetails = {
id: checkListId,
...checkListData
};
records.checkLists.push(checkListDetails);
}
}
console.log(`successfully fetched ${records.tasks.length} tasks and ${records.checkLists.length} checklists`);
return records;
} catch (error) {
console.log('Error fetching docs ====>', error);
}
}
// Call the function to fetch records
getTasksAndCheckLists('someAccountId')
.then(result => {
console.log(result);
return true;
})
.catch(error => {
console.error('Error fetching docs ===>', error);
return false;
});
执行统计:
在 220.532 秒内成功获取 627 个任务和 51 个清单
我得出的结论是,检索清单会减慢整个过程,因为检索任务相当快。
所以我的问题如下:
- 有什么办法可以优化上面的文档检索 代码?
- 有什么办法可以找回子的文件 通过重构数据和使用 collectionGroup 查询更快地收集 等等?
谢谢。
【问题讨论】:
-
减少嵌套集合不是更好吗,阅读this
-
您共享的文档是针对实时数据库的,而不是针对云 Firestore 的。两者都不同,因为与 RTDB 不同,firestore 查询很浅。将清单存储为子集合允许我按需延迟加载它,并为我提供分页和排序的灵活性,而不是将其存储为任务中的一个大数组。我没有像项目和任务一样将清单存储为顶级集合的原因是因为项目和任务是独立的实体,可以独立存在,但清单并非如此。
-
@vipul 我想我的数据插图可能看起来像 RTDB。对此我深表歉意。
-
我很抱歉,我把 Firestore 误认为是 RTDB,是的,Firestore 赋予了存储嵌套数据的灵活性。
-
只是想添加这个,有 db.collectionGroup 功能可能会帮助你,如果你有时间你可以检查这个out
标签: javascript firebase google-cloud-firestore