您将如何在 Firebase 中对用户和好友集合进行建模?



我正在尝试使用Firebase创建一个数据库(json(。 我搜索了文档和网络,但找不到明确的开始方式。 我想要一个用户数据库。 每个用户(表示为 UID(都应该有一个昵称和一个朋友列表。

我尝试制作一个看起来像这样的 .json 文件:

{
users:{
}
}

并将其添加到Firebase控制台以开始使用,但它不起作用。 我该怎么做?

数据库应如下所示:

{
users:{
UID:{
nickname: hello
friends: UID2
}
UID2:{
nickname: world
friends: UID
}
}

我不知道我是否做对了,所以我真的很感激你们在这个问题上能给我的任何帮助。 提前感谢!

似乎是一个很好的起点。不过,我会做两个更改。

  1. 保持列表是朋友分开的
  2. 将好友保留为集合,而不是单个值或数组

保持列表是朋友分开的

使用 Firebase 数据库时,一个基本建议是将数据结构保持浅/扁平。造成这种情况的原因有很多,你至少有两个。

  1. 使用当前数据结构,假设您要显示用户名列表。您只能通过收听/users来获取该列表。这意味着您不仅可以获得每个用户的用户名,还可以获取他们的朋友列表。您向用户显示所有这些数据的可能性很小,因此这意味着您只是浪费了他们的一些带宽。

  2. 假设您希望允许所有人阅读用户名列表。但是您只希望每个用户能够阅读自己的朋友列表。您当前的数据结构使这变得困难,因为权限级联和规则不是过滤器。

更好的结构是将用户配置文件列表(目前只是他们的名字(与每个用户的好友列表分开。

将朋友作为一组

您当前只有friends属性的单个值。当你开始构建应用时,你需要存储多个朋友。最常见的是存储 UIDS 的数组或列表:

[ UID1, UID2, UID3 ]

{
"-K.......1": "UID1"
"-K.......5": "UID2"
"-K.......9": "UID3"
}

不幸的是,这些是此数据结构的错误类型。数组和第二个集合都是列表:(可能(非唯一值的有序集合。但是朋友的集合不必订购,它必须是唯一的。我要么在集合中,要么不在那里,我不能多次在那里,顺序通常无关紧要。这就是为什么您经常最终寻找上述模型的friends.contains("UID1")ref.orderByValue().equalTo("UID1")操作的原因。

更好的模型是将数据存储为一个集合。集合是无序值的集合,这些值必须是唯一的。非常适合一群朋友。为了将其存储在 Firebase 中,我们使用 UID 作为集合的键。由于我们不能在没有值的情况下存储密钥,因此我们使用true作为虚拟值。

因此,这导致了以下数据模型:

{
users:{
UID:{
nickname: hello
}
UID2:{
nickname: world
}
}
friends:{
UID:{
UID2: true
}
UID2:{
UID: true
}
}
}

关于NoSQL数据建模,特别是Firebase,还有很多话要说/学习。要了解这一点,我建议阅读NoSQL数据建模并观看Firebase for SQL开发人员。

我保留了一个Friends集合,其中users字段是 2 个用户 ID 的数组:['user1', 'user2']

获取用户的好友很容易:

friendsCollection.where("users", "array-contains", "user1").get()

这应该会为您提供出现 user1 的所有文档。

现在棘手的部分是如何查询一个朋友。理想情况下,Firebase 将支持array-contains中的多个值,但他们不会这样做:https://github.com/firebase/firebase-js-sdk/issues/1169

因此,他们解决此问题的方法是在添加文档之前规范化users列表。基本上,我利用JS的真实性来检查哪个userId更大,哪个更小,然后按顺序列出一个列表。

添加好友时:

const user1 = sentBy > sentTo ? sentBy : sentTo
const user2 = sentBy > sentTo ? sentTo : sentBy
const friends = { users: [user1, user2] }
await friendsCollection.add(friends)

这基本上保证了友谊中的一员将始终以相同的顺序列出,因此在查询时,您可以只

await friendsCollection.where("users", "==", [user1, user2]).get()

这显然只有效,因为我相信列表将始终包含 2 个项目,并且相信 JS 的真实性将确定性地工作,但它是这个特定问题的一个很好的解决方案。

最新更新