在线/离线用户功能 Firestore 或实时的更好解决方案是啥?
Posted
技术标签:
【中文标题】在线/离线用户功能 Firestore 或实时的更好解决方案是啥?【英文标题】:What is better solution for online/offline user feature firestore or realtime?在线/离线用户功能 Firestore 或实时的更好解决方案是什么? 【发布时间】:2020-05-20 13:08:28 【问题描述】:我有一个用户数据库。需要实现只显示在线用户的列表。不幸的是实时不会按键过滤。所以只有在 Firestore 中才有可能。但是 Firestore 会为每个写入/读取/更新操作收费,因此使用该功能可能非常昂贵,因为用户一直处于离线/在线状态,并且会有很多写入/读取/更新操作。作为一种解决方案,我实时做了单独的表,它只保存在线用户,在这里我不需要为写入/读取/更新付费。但与此同时,它正在复制数据库,这也不是一个好的做法。
您能否从“价格”和“清洁”的角度分享您对哪种解决方案更好的想法。为 Firestore 付费并使用一个 db,还是使用两个 db 但不为每次操作付费?
【问题讨论】:
当您说 FB rtdb 无法过滤密钥以及为什么您不能将其用于您的整个需求时,不清楚您的意思。您能否展示这两种数据库结构,也许这将有助于澄清您的问题。 @GrahamD 如果您有 100 个用户,则无法通过密钥过滤。每个用户都有关键的“性别”,其中 40% 是女性,60% 是男性。从技术上讲,您不能在 rtdb 中只接受女性。只有在 Firestore 中才有可能。 @GrahamD 如果您有任何问题,请告诉我 【参考方案1】:在线/离线用户功能 Firestore 或实时有什么更好的解决方案?
这取决于您的要求,但您应该不考虑使用其中一种。两者都用没有错。
不幸的是实时不能按键过滤。
如果您查看文档,有一个名为 sorting and filtering data 的部分,您会在其中找到一个名为 orderByKey()
的方法:
按子键排序结果。
因此实际上可以过滤查询结果并同时对它们进行排序。
作为一种解决方案,我实时创建了单独的表格,只保存在线用户,在这里我不需要为写入/读取/更新付费。
这是一个很好的解决方案,您可以继续使用。实际上,Cloud Firestore 和 Firebase 实时数据库可以很好地协同工作。
但与此同时,它正在复制数据库,这也不是一个好习惯。
哦,原来如此。这种做法称为非规范化,是 Firebase 的常见做法。为了更好地理解,我建议您观看此视频 Denormalization is normal with the Firebase Database 并查看以下帖子中的答案:
What is denormalization in Firebase Cloud Firestore?因此,您可以对数据进行非规范化以获取实际上不可能的查询,或者在涉及 Cloud Firestore 时节省一些写入操作。
您能否从“价格”和“清洁”的角度分享您对哪种解决方案更好的看法。为 Firestore 付费并使用一个 db,还是使用两个 db 但不为每次操作付费?
同时使用它们。
【讨论】:
非常感谢您的回答。我发现它很有帮助。但也许在那个点 rtdb 更好使用之前,有一个零点(可以是列表中的用户数,比如说 2000)。但是在那之后(2000+)最好使用firestore,因为维护和定价会更好? 据我所知,没有这点。 Cloud Firestore 和 Firebase 实时数据库是两个可以很好地协同工作的不同产品。 “点”可能是其中一个或另一个超出您的预算。因此,您可以根据需要使用其中一种。orderByKey
不幸的是只排序而不是过滤
@BorisRuzanov 没错,但您可以将它与过滤方法yourRef.orderByChild("yourProperty").equalTo("yourValue");
一起使用。看,您可以同时订购和过滤。
我已经测试过了。很高兴了解该解决方案,但是对于我的结构,它不会起作用,因为 order 字段和 equal 是不同的。我需要通过rating
订购,但只能获得等于在线的online_status
字段。但我会将其标记为答案,因为它假设适合基本功能【参考方案2】:
您可以在 FB RTDB 中执行过滤,它不像 Firestore 那样复杂或灵活(您一次只能过滤一个键或值)但如果它像您的示例一样微不足道,那么它当然是可能的(您需要在生产中使用索引来提高性能并限制数据下载)。
在这样的数据库结构上(忽略“根”下不是“用户”的节点,我在开发过程中使用这个“根”节点进行多个代码测试):
并使用此代码(在 Flutter/Dart 中,但相同的参数在其他语言中可用):
_referenceRoot
.child("root")
.child("users")
.orderByChild("gender")
.equalTo("male")
.once()
.then(
(DataSnapshot snapshot)
print("snapshot.value: $snapshot.value");
if (snapshot.value != null)
print("snapshot.key: $snapshot.key");
,
);
我得到这个输出,即只有男性用户。请注意,在快照中,所选用户是无序的:
I/flutter (4307):snapshot.value:a2:头发:棕色,性别:男性,年龄:20,a3:头发:棕色,性别:男性,年龄:20,a4:头发:棕色,性别:男性,年龄:20,a6:头发:棕色,性别:男性,年龄:20,a8:头发:棕色,性别:男性,年龄:20,a9:头发:棕色,性别:男,年龄:20,a0:头发:棕色,性别:男,年龄:20 I/flutter(4307):snapshot.key:用户
有关可能的更多详细信息,请参阅此内容:https://firebase.google.com/docs/database/rest/retrieve-data
所以,为了回答您的具体问题,如果您需要做的过滤是微不足道的,我会只使用 FB RTDB。如果更复杂,则必须是 Firestore。您需要对估计的数据存储/下载量与 db 调用和存储量进行数学计算,以最大限度地降低成本。
【讨论】:
非常感谢您的回答。我发现它很有帮助。但也许在那个点 rtdb 更好使用之前,有一个零点(可以是列表中的用户数,比如说 2000)。但是在那之后(2000+)最好使用firestore,因为维护和定价会更好? 这是给你的工作。我推荐 Excel what-ifing :-)以上是关于在线/离线用户功能 Firestore 或实时的更好解决方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章