在 Firebase 中构建聊天应用程序的数据
Posted
技术标签:
【中文标题】在 Firebase 中构建聊天应用程序的数据【英文标题】:Structuring data for chat app in Firebase 【发布时间】:2016-09-27 15:16:33 【问题描述】:我正在关注 structuring data 的 Firebase 指南以获取聊天应用程序。他们提出了如下所示的结构。
// Chats contains only meta info about each conversation
// stored under the chats's unique ID
"chats":
"one":
"title": "Historical Tech Pioneers",
"lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
"timestamp": 1459361875666
,
"two": ... ,
"three": ...
,
// Conversation members are easily accessible
// and stored by chat conversation ID
"members":
// we'll talk about indices like this below
"one":
"ghopper": true,
"alovelace": true,
"eclarke": true
,
"two": ... ,
"three": ...
,
// Messages are separate from data we may want to iterate quickly
// but still easily paginated and queried, and organized by chat
// converation ID
"messages":
"one":
"m1":
"name": "eclarke",
"message": "The relay seems to be malfunctioning.",
"timestamp": 1459361875337
,
"m2": ... ,
"m3": ...
,
"two": ... ,
"three": ...
我如何构建我的用户数据,以便我可以轻松地显示他们所属的所有聊天的列表,并为每个聊天显示最后一条消息和时间戳。如果我执行以下结构:
"users":
"ghopper":
"name": "Gary Hopper",
"chats":
"one: true",
"two": true
,
"alovelace" ...
,
我可以通过以下方式轻松获取特定用户(例如 ghopper)的每个聊天组的列表:
ref.child("users").child("ghopper").child("chats").observeSingleEventOfType(.Value, withBlock: (snapshot) in
//do something with data
但是,我不会在此快照中包含 lastMessage 和时间戳。我需要做什么才能访问这些数据?
为每个用户复制所有这些数据?即添加 users/ghopper/chats/one/ "lastMessage": "ghopper: Relay failure found. Cause: moth.", "timestamp" : 1459361875666 为用户参与的每个聊天查询“chats/specificGroupId”(添加多个侦听器)? 其他方式?【问题讨论】:
【参考方案1】:如何组织我的用户数据,以便我可以轻松地显示列表 他们参与的所有聊天,并且每个聊天都显示 最后一条消息和时间戳。
通过添加聊天节点中的用户来稍微改变聊天结构
"chats":
"one":
"title": "Historical Tech Pioneers",
"lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
"timestamp": 1459361875666
users
uid_1: true
uid_3: true
,
"two": ... ,
然后您可以深入查询特定用户参与的所有聊天 - 这将返回 uid_3 参与的聊天
chatsRef.queryOrderedByChild("users/uid_3").queryEqualToValue(true)
.observeSingleEventOfType(.Value, withBlock: snapshot in
//.Value can return multiple nodes within the snapshot so iterate over them
for child in snapshot.children
let lastmsg = child.value["lastMessage"] as! String
let timestamp = child.value["timestamp"] as! String
print(lastmsg)
print(timestamp)
)
请注意,当通过 auth.uid 创建用户时,每个 firebase 用户都有一个谨慎的用户 ID。这应该(通常)用作每个用户的密钥。
【讨论】:
您好,Jay,感谢您的回答。我已经尝试过您的解决方案,它似乎可以解决问题。但是考虑到我需要查看所有“聊天/”才能找到用户参与的所有聊天,一旦我有很多用户,这个操作会不会变得太昂贵? @Nilsymbol 很高兴它成功了!看起来您并没有拉下兆字节的数据,只是几百个带有一些子节点的节点。 Firebase 速度非常快,因此在数千个节点上进行这样的查询非常快;它甚至不会让 Firebase 呼吸困难。我们已经测试过了! @Jay 我了解大部分结构,只是不了解用户在“聊天”子项中的表示方式。它是用户 uid 的数组吗?您能否再解释一下布尔值与 uid 的关联?非常感谢! -科尔比 @Jay 忽略最后的评论,我现在明白了。一个小小的实验消除了我的困惑。谢谢! @Jay 安全性如何融入其中?如果我的用户不是聊天的一部分并且我将自己添加到该聊天中 - 这意味着我可以查询它 - 这意味着所有用户都可以阅读所有聊天。如果现有聊天成员添加了我 - 那么该聊天成员必须知道我的用户 ID - 这意味着所有用户都可以读取所有用户。有没有解决的办法?如何更新索引?【参考方案2】:在您拥有用户所在的所有聊天列表的区块中,您可以这样做:
var dictionary: [String: Long]
var lastMessage: String
for chat in listOfChatsUserIsIn
ref.child("chats").child("\(chat)").child("lastMessage").observeSingleEventOfType(.Value, withBlock: (snapshot) in
lastMessage = snapshot
ref.child("chats").child("\(chat)").child("timestamp").observeSingleEventOfType(.Value, withBlock: (snapshot) in
//add timestamp and last message to dictionary
我不知道我的语法有多正确。还在学习firebase。但是,我认为这基本上是您的第二个建议。不知道您将如何获取数据。这将是 O(2n) 虽然这还不错。
[[更新 1]]
我对我的代码很懒惰。我放了 lastMessage = snapshot 来保存它,这样你就可以在下一个块中将它添加到字典中。
至于 Firebase 是异步的。我认为只要您使用时间戳或消息作为键,另一个作为字典中的值,这仍然有效。它可能会乱序填充,但您以后总是可以按时间戳对其进行排序。虽然,是的,这可能不是最佳实践。
Jay,我喜欢你的解决方案。您是否还必须列出uid_2: false
?
不幸的是,随着用户 -> inf 和聊天 -> inf,这两个数据库结构似乎都增长了 n^2。
【讨论】:
由于您没有使用该变量,lastMesssage = snapshot 的功能是什么?此外,在块(闭包)中使用 self.variable 名称是一种很好的做法。此外,第一个 ref.child 中的 ref.child 是重复的,因此它将读取相同的数据。最大的问题是 Firebase 是异步的,并且紧密的 for 循环运行速度会比观察块中返回的数据快 方式,所以我认为我们遇到了一些数据完整性问题 - 可能应该让 Firebase 异步完成它的“东西”。 回答你的答案中的问题.... 不,uid_2: false 不需要,因为它不存在,默认情况下它可能是 false(取决于它的编码)。不,数据库不会成倍增长。如果您有 10 个用户和 1 个聊天,则所有 10 个用户都在该聊天中,因此唯一增长的将是聊天中的用户节点(在我的回答中)同样,如果您有 1000 个用户和 100 个聊天,每个聊天与两个用户,仍然只有 100 个聊天,每个聊天都有一个用户节点和两个用户。即使有 1000 个用户和 1000 个聊天,这也不是大量的数据。以上是关于在 Firebase 中构建聊天应用程序的数据的主要内容,如果未能解决你的问题,请参考以下文章
使用 Firebase 和 Flutter 构建聊天应用程序的最简单方法是啥
使用 Angularjs 和 Firebase 构建聊天应用程序
用于聊天应用的 Firebase 实时数据库或 Firestore? [关闭]
Firebase 聊天应用 setValue 在公共数据库中失败?