angular - Angular + Firebase firestore - 对文档的内部订阅在初始订阅时返回两个值
问题描述
我在 Angular 11+ 上使用 AngularFire 作为 Firebase 的 API。
我的应用程序的域是实时拍卖
理想情况下,我想做的是阅读所有文档,然后订阅每个文档以进行更改。
我目前的麻烦是我在 Firestore 上的读取次数。
我的收藏阅读将产生 N 次阅读。但是订阅每个文档会产生额外的读取,默认情况下会产生 2N 次读取,这似乎是不可避免的。
但我想这比在集合上留下订阅并在每次更新集合中的某些内容时接收 N 读取要好。
因此,使用下面的示例代码,我对集合进行查询,然后对文档进行另一个查询。简化只是为了复制。
this.store.collection("users").valueChanges()
.pipe(
take(1),
concatMap(() => this.store.doc("user/1").valueChanges())
)
.subscribe(console.log(user));
然而,Inner observable 会发射 2 次。
一次added
具有modified
快照更改类型。
所以我的问题是:
为什么我的内部 observable 在初始订阅时连续发出两次,而在我看来它应该只发出一次。
如果这两个发出都算作 Firestore 上的读取,则这将产生 3N 次读取。
通过我在 firestore 监控页面上的测试,似乎是这样,因为在 400 个文档页面上,我在 firestore 上记录了大约 1200 次读取并计入定价。
我在示例代码中可能做错了什么?
有没有人建议我应该如何以更少的读取更有效地检索数据?
我是否应该切换到 RTDB,它似乎提供了更慷慨的 10GB 数据输出,这可能对我的读取量更好?
编辑:
所以我刚刚用 angularfire API 测试了 firebase RTDB。
像上面这样的示例代码将使内部 observable 仅按预期发出 1 个值,并且每个项目更改 1 个。这是预期的。
我仍然不清楚为什么 firestore 实现会发出 2 个值,这些值既被视为已读取,又被计为定价。
结束代码看起来像这样:
this.db.list<AuctionItem>(`auctions/1/items`)
.valueChanges()
.pipe(
take(1),
tap(items => this.itemsToRender = items),
mergeMap(items => [...items]),
mergeMap((item: AuctionItem) => this.db.object(`auctions/1/items/${item.id}`).valueChanges() as Observable<AuctionItem>),
)
.subscribe(change => {
// do work when item updates
})
仍然不确定为什么firestore没有按预期为我工作。考虑使用部分 firestore + RTDB 以获得最佳使用,因为即使有 50k 免费,我在 firestore 上的读取量也很高。
解决方案
这是我在你的情况下会做的:
- 执行 onSnapshot() 查询,(第一次读取操作)--> 但将结果限制为 10 或 20。(便宜!)
- 在用户滚动 - >加载更多。(Firestore 分页参考)
- 当文档更改时 --> 更新显示的数据
在侦听更改时,您只需为发生更改的文档再次收费,而不是您已经查询但未获得任何更新的文档。
有关听众定价的更多详细信息,请观看此视频(尤其是 3:16)
推荐阅读
- c# - 为什么我的子弹穿过我的敌人而没有检测到碰撞?
- html - 我该怎么做才能保持动态列表?
- vb.net - 无法将参数传递给 Telerik 报告
- c# - Xamarin.Mac 应用程序在与最终用户的文件系统交互时挂起
- javascript - react-native 错误:[未处理的承诺拒绝:错误:获取 Expo 令牌时遇到错误:TypeError:网络请求失败。]
- angular - ngForOf 中的重复 ID 生成 - Angular
- php - 增加 WooCommerce 购物车中每个类别计数的运费
- c - 试图从另一个 char 指针分配一个 char 指针。为什么会出现段错误?
- typescript - 使用 'as Movie[]' 而不是 '
' @typescript-eslint/一致类型断言 - c# - 如何在 Xamarin 表单中将图标放在标签旁边