【问题标题】:Firebase database structure for chat application聊天应用程序的 Firebase 数据库结构
【发布时间】:2018-06-01 10:04:26
【问题描述】:

我正在尝试为聊天系统构建一个 firebase 数据库。我想要实现的是用户成功登录后,他们会看到他们发送给不同用户的消息列表。每个消息预览都会显示最后一条消息。然后,用户可以选择消息以查看完整的聊天详细信息。它应该像 Facebook Messenger 一样工作。

我的设计结构是这样的:

chatMessage
    sender *(Assume this one is user)*
        threads
            threadID1
                messageID1
                    datetime, content, receiver, status
                messageID2
                    datetime, content, receiver, status
            threadID2
                messageID1
                    datetime, content, receiver, status
                messageID2
                    datetime, content, receiver, status
    sender *(Assume this one is admin)*
         threads
            threadID1
                messageID1
                    datetime, content, receiver, status
                messageID2
                    datetime, content, receiver, status

上面的设计让我知道假设 userID1 登录,我可以检索他发送的所有消息。但是,我无法知道消息之前是否有任何回复,因此我无法检索最后一条消息。

我如何才能真正重组它以实现我上面提到的目标?有什么建议吗?

谢谢!

【问题讨论】:

    标签: firebase firebase-realtime-database


    【解决方案1】:

    听起来你想要:

    1. 在用户之间建立聊天“房间”
    2. 显示每个用户的聊天室列表,以及该聊天室的最新消息

    如果这些是您的要求,我会在您的数据库中精确建模。

    因此,对于每个聊天室(一组特定用户之间的聊天),为该聊天室建模:

    chats: {
      $roomId: {
        $messageId: {
          senderId: "..."
          message: "..."
        }
      }
    }
    

    现在为每个用户建模一个单独的聊天列表和最新消息:

    userRooms: {
      $uid: {
        $roomId: {
          "message: "..."
        }
      }
    }
    

    现在,每当用户向房间发布消息时,您都需要将该消息推送到 /chats/$roomId并且为该聊天室中的每个用户将消息写入 /userRooms/$uid/$roomId(覆盖在那里退出消息)。

    这种类型的数据复制称为扇出数据,因为您将单个 sn-p 信息传播到数据库中的多个位置。这在 NoSQL 数据库中很常见,也是它们可扩展性如此之好的部分原因:它们以写入复杂性换取读取性能。

    【讨论】:

    • 嘿,非常感谢!但只是为了再次确认我的理解,/chats/$roomId 基本上存储了所有用户针对某个“房间”的所有消息。假设 A 发送消息给管理员,管理员回复 A,所有这些都应该存储在同一个 $roomId 下。然后对于/userRooms/$uid/$roomId,这是为了便于某些用户检索所有“房间”以便在用户登录后将它们列出。我的理解是否正确?
    • @hyperfkcb 这是一个很棒的答案!扩大一点;这个结构确实显示了最新的消息,它不包括它来自谁或者可能是时间戳。一个简单的更改是,不再复制 userRooms 中的消息文本,而是存储对最新消息的引用:userRooms/$uid/$roomid/$messageId = true。然后,当用户登录应用程序时,可以读取该节点,该节点将检索最新的特定消息。然后阅读消息节点以获取更多信息。是的,这是两次读取,但根据需要的数据增加了一点灵活性。 :-)
    • 感谢杰伊的补充!这确实是另一种选择:只复制最新消息的密钥。我更喜欢复制所需的实际数据,因为它消除了额外读取的需要。但正如所说:这是一种偏好,而不是建议。 :-)
    • @Jay Ahh 我明白了。让我再次与您确认我的理解,所以您的意思是每次从特定聊天室发送新消息时更新 userRooms/$uid/$roomid/ 下的 $messageId?所以基本上通过获取 messageId,我可以简单地检索所有其他信息,如时间戳等与消息本身一起出现的信息,而不仅仅是消息文本?
    • @hyperfkcb 是的 - 你明白了!如果您只需要消息文本,那么弗兰克的回答将满足您的一切需求。如果您想要的数据不仅仅是消息,那么您可以通过它的 messageId 保留对消息的引用。
    猜你喜欢
    • 2017-11-16
    • 2018-03-03
    • 2017-01-04
    • 2016-06-28
    • 2016-09-27
    • 1970-01-01
    • 2019-02-12
    • 2015-12-05
    • 1970-01-01
    相关资源
    最近更新 更多