在线/离线用户功能 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 或实时的更好解决方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用实时更新将在线用户显示为绿色,将离线用户显示为灰色

技术分享| 基于RTM 实现的呼叫邀请如何添加推送功能?

技术分享| 基于RTM 实现的呼叫邀请如何添加推送功能?

Android 中的 Firebase 事件记录离线和在线 [关闭]

在 Cloud Firestore 中管理在线状态

QQ好友在线/离线,怎么测试?