Angular:增加Firebase数据库中的查询加载时间



我有一个angular应用程序,我在其中查询我的firebase数据库,如下所示:

constructor() {
this.getData();
}
getData() {
this.projectSubscription$ = this.dataService.getAllProjects()
.pipe(
map((projects: any) => 
projects.map(sc=> ({ key: sc.key, ...sc.payload.val() }))
),
switchMap(appUsers => this.dataService.getAllAppUsers()
.pipe(
map((admins: any)  => 
appUsers.map(proj =>{
const match: any = admins.find(admin => admin.key === proj.admin);
return {...proj, imgArr: this.mapObjectToArray(proj.images), adminUser: match.payload.val()}
})
)
)
)
).subscribe(res => {
this.loadingState = false;
this.projects = res.reverse();
});
}
mapObjectToArray = (obj: any) => {
const mappedDatas = [];
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
mappedDatas.push({ ...obj[key], id: key }); 
}
}
return mappedDatas;
};

以下是我在dataService内部查询的内容:

getAllProjects() {
return this.afDatabase.list('/projects/', ref=>ref.orderByChild('createdAt')).snapshotChanges();
}
getAllAppUsers() {
return this.afDatabase.list('/appUsers/', ref=>ref.orderByChild('name')).snapshotChanges();
}

我面临的问题是,我有400行数据正在尝试加载,加载大约需要30秒,这太高了。知道我如何在更快的时间内查询这个吗?

我们无法知道30s是否合理,因为这取决于加载的数据量、客户端的连接延迟和带宽,以及我们无法知道/控制的更多因素。

但需要记住的一点是,你要执行400个查询来获取每个应用程序的用户,这可能对性能不太好。

您可以考虑的事项:

  • 预加载所有用户一次,然后将该列表用于每个项目
  • 将每个用户的名称复制到每个项目中,这样就根本不需要连接任何数据

如果你来自关系数据库的背景,后者可能违反直觉,但它实际上在NoSQL数据建模中非常常见,也是NoSQL数据库规模如此之大的原因之一。

我提出了3个解决方案。

1.寻呼

与其在应用程序加载时返回所有这些文档,不如将它们限制在10个以内,并记录最后一个。然后显示10(或任意基数)

然后以用户必须单击下一个的方式制作UI,或者当用户滚动时,根据上一个文档的字段信息获取下一个集合。

我假设您需要在某个表或列表中显示所有提取的数据,因此让UI对数据进行分页应该是有意义的。

2.装载机

在网站加载时显示一些加载程序UI。然后,当所有文档都已提取时,您可以隐藏加载程序并根据需要显示数据。您可以使用一些自定义的加载程序,或者从任何丰富的库中进行选择,或者使用Angular Material 中的mat进度微调器

3.onCall云功能

如果您尝试通过onCall云功能让它们运行呢?它的速度会更快,因为这只是应用程序发出的一个请求,而Firebase的云功能在谷歌的数据中心内非常快速。

考虑到用户的网络可能迭代文档的速度很慢,但云函数会一次返回所有文档,这可能会给你想要的。

我想只有当你真的需要在网站加载时同时显示所有数据时,你才能选择这个选项。

。。。成本说明

每次加载一个给定的网站时获取400个或更多的文档可能会很昂贵。如果有很多用户频繁访问该网站,费用会很高。Firebase的成本也会增加,因为您每次阅读文档都会收取费用。

查看是否可以优化数据结构以避免获取过多数据。

如果这是一个管理面板,或者像这样获取所有用户的操作很少,在这种情况下成本不高,那么这就不适用于你。