尝试了解在我的场景中使用 firebase 数据库进行非规范化工作的效果如何

Posted

技术标签:

【中文标题】尝试了解在我的场景中使用 firebase 数据库进行非规范化工作的效果如何【英文标题】:Try to understand how well can denormalize work with firebase database in my scenario 【发布时间】:2017-10-25 10:46:49 【问题描述】:

所以基本上我正在使用 mysql 构建所有以前的应用程序来存储数据并考虑切换到 firebase 数据库,这让我感觉有点疯狂。我正在尝试实现一个聊天系统,但是在理解它的工作原理时会遇到一些麻烦。基于Denormalizing Your Data is Normal,我了解了非规范化如何工作的想法和概念。

我知道我可以创建一个消息结构来存储聊天消息,如下所示(来自doc 的示例)

"messages": 
    "one": 
      "m1": 
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      ,
      "m2":  ... ,
      "m3":  ... 
    ,
    "two":  ... ,
    "three":  ... 

但这是我的场景,假设我有一个最多可以包含 1000 人的群聊。

场景 1: 我允许用户删除消息。当用户在群聊中发送了一些粗俗的内容,并且其中一个成员感到不舒服并决定删除它时,这将导致其他用户无法观看该消息。 场景 2 如果其中一名成员被管理员踢出,我希望他在被踢出之前仍然能够观看上一条消息。

对于SQL 版本中的场景一,我创建了一个表,其中包含用户删除时带有用户ID 的消息ID,并执行如下查询,该消息仍可供其他用户使用。

SELECT * FROM message WHERE roomId = $userId AND messageId NOT IN ($messageId) 

但是firebase数据库不支持这个功能,所以我现在唯一能想到的方法就是把每条新消息都写到所有的成员树中

"messages": 
    "john": 
      "m1": 
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337,
        "groupId" : "1"
      ,
      "m2":  ... ,
      "m3":  ... 
    ,
    "jimmy":  ... ,
    "paul":  ... 

因此,当用户删除消息时,我可以轻松地将其从他自己的消息节点中删除,以便其他用户仍然可以使用该消息。

如果群聊多达 1000 人,我可能需要写入 1000 个用户节点树,这让我感到困惑,在 firebase 数据库中写入如此数量的数据时会出现问题吗?我的意思是像写作时间很长,磁盘空间等问题。或者有更好的方法吗?如果这很好,我想我也可以解决我的场景 2。如果从标题中产生任何误解,我感到非常抱歉,因为从sql到no sql真的很难切换。

感谢任何提前。

【问题讨论】:

【参考方案1】:

不,您不需要向 1000 个用户节点写入数据,您只需写入一次。为此,您需要有一个如下所示的数据库结构:

Firebase-root
  |
  ---- Groups
  |      |
  |      ---- groupId
  |             |
  |             ---- groupName: "android"
  |             |
  |             ---- users
  |             |      |
  |             |      ---- userId1: true
  |             |      |
  |             |      ---- userId2: true
  |             |
  |             ---- messages
  |                    |
  |                    ---- messageId1: "Hello" 
  |                    |
  |                    ---- messageId2: "Hy" 
  |                    |
  |                    //and so on
  |
  ---- messages
          |
          ---- messageId1
          |      |
          |      ---- users
          |             |
          |             ---- userId1: true
          |             |
          |             ---- userId2: true
          |
          ---- messageId2
                 |
                 ---- users
                        |
                        ---- userId1: true
                        |
                        ---- userId2: false // false for second message

希望对你有帮助。

【讨论】:

谢谢回复,但我需要的是当 userId1 删除 messageId1 但我仍然希望 userId2 可以使用 messageId1 消息时。 您需要为每个可以看到或看不到消息的用户添加messages 节点限制。因此,在这种情况下,您需要将 userId2 设置为 false。对于第二条消息。请查看我的更新答案。 好的,这让我知道如何实现它。实际上我需要知道的是这个操作是否需要很长时间才能编写或者它很糟糕,因为如果我在群聊中有 1000 个用户,我需要为每条新传入消息编写限制键。没事吧? 在一个组中有 1000 个用户,这是一个相对较大的数字,但要确切了解发生了什么,我建议您以编程方式生成这 1000 个用户,并在现实世界的场景中查看。

以上是关于尝试了解在我的场景中使用 firebase 数据库进行非规范化工作的效果如何的主要内容,如果未能解决你的问题,请参考以下文章

在我的Grocery应用程序中被firebase推送通知卡住了。

如何在 Firebase 中使用 onSnapshot?无法在我的应用中运行

我正在尝试获取对我的 Firebase 数据库子项的正确引用并在我的 RecyclerView 中设置值,但我遇到了一些问题

如何在我的java类中将firebase值存储为全局整数[重复]

[使用AWS lambda函数每1小时更新Firebase数据库

Flutter 函数使用 Firebase 返回空列表