问题是我为Firebase应用程序定义的数据结构。 然而,它正在发挥作用,我对效率和可扩展性表示怀疑。
想象一下只有一个全球聊天室的聊天应用程序 但您只会看到与您有关系的用户发来的消息。 在这种意义上,“关系”意味着您共享相同的组成员资格。 这些是小组:
+---------+---------+---------+
| Group A | Group B | Group C |
+---------+---------+---------+
| User1 | User4 | User7 |
| User2 | User5 | User8 |
| User3 | User6 | User1 |
+---------+---------+---------+
请注意,User1是A组和C组的成员。 概念是User1将看到用户2,3,7和8发布的消息 而User4只会看到来自用户5和6的消息。 为此,每个用户的关系存储在Firebase实时数据库中,如下所示:
Friends
├── User1
│ ├── User2: true
│ ├── User3: true
│ ├── User7: true
│ └── User8: true
├── User2
├── User1: true
└── User3: true
等等。出于演示目的,我在这里使用用户名,实际上,这些是Firebase UID。 显然,这需要将一些(users_per_group)²条目写入数据库。 每组可能的组和用户数量不受限制。 这些消息会添加到Firebase中,如下所示:
Messages
├── User1
│ ├── timestamp
│ │ └── message: "This is a message"
│ ├── timestamp
│ │ └── message: "This is another message"
├── User2
├── timestamp
│ └── message: "..."
通过以下Firebase安全规则可以轻松实现权限的实际执行:
"Messages": {
"$uid": {
// allow read only if the current user is a friend of the message creator
// OR if the user is the creator of the message
".read": "(root.child('Friends/' + $uid + '/' + auth.uid).val() === true || $uid === auth.uid)"
}
}
这是构建数据的推荐方法吗? 由于跟踪用户关系所需的大量数据,我有点不确定。
答案 0 :(得分:2)
当我们谈论效率和可扩展性时,Firebase中最重要的规则是尽可能使数据变得扁平化。根据这条规则,我建议你改造你的数据库:
firebase-url
|
--- users
| |
| ---- userId_1
| | |
| | ---- userName: "John"
| | |
| | ---- userAge: 30
| | |
| | ---- groups
| | |
| | ---- groupName1 : true
| | |
| | ---- groupName2 : true
| |
| ---- userId_2
| |
| ---- userName: "Anna"
| |
| ---- userAge: 25
| |
| ---- groups
| |
| ---- groupName3 : true
| |
| ---- groupName4 : true
|
---- groups
| |
| ---- groupIdId_1
| |
| ---- groupName: "groupName1"
| |
| ---- users
| |
| ---- userId_1: true
| |
| ---- userId_2: true
|
--- messages
|
---- groupId_1
|
---- messageId_1
| |
| ---- messageText: "Hello!"
| |
| ---- messageTimeStamp: 1492189663846
|
---- messageId_2
|
---- messageText: "Hy!"
|
---- messageTimeStamp: 1492189685692
通过这种方式,您可以非常简单地查询数据库,以显示属于单个组的所有用户:firebase-url/groups/groupId/users/
。用户为appart的所有组:firebase-url/users/userId/groups/
以及来自单个组的所有邮件:firebase-url/groupId_1/
要详细了解如何正确构建Firebase数据库,请阅读此post。
希望它有所帮助。
答案 1 :(得分:1)
很抱歉让您失望,但遗憾的是,您无法将此数据结构用于您想要实现的目标。
首先,只要组中没有太多用户,数据树的性能就应该很好。我通过重建您概述的数据结构并在创建朋友" Firebase实时数据库中它们之间的关系。结果如下:
Added user #10. Needed time: 0.00156599283218384 seconds
Added user #30. Needed time: 0.00276100635528564 seconds
Added user #50. Needed time: 0.00490301847457886 seconds
Added user #100. Needed time: 0.013949990272522 seconds
Added user #150. Needed time: 0.0460770130157471 seconds
Added user #200. Needed time: 0.0947499871253967 seconds
Added user #300. Needed time: 0.451290011405945 seconds
Added user #400. Needed time: 1.81872600317001 seconds
正如您所看到的,对于小组来说,表现似乎完全没问题。
但问题主要不在于您希望如何存储数据,而在于您希望如何获取数据。您写道,您希望使用数据库规则来获取用户可以看到的所有消息,具体取决于他的朋友"关系。但这是某种过滤机制,在Firebase实时数据库中禁止/无法使用数据库规则进行过滤。
规则不是过滤器
规则以原子方式应用。这意味着读或写 如果该位置没有规则,则操作立即失败 或者在授予访问权限的父级位置。即使每一个受到影响 子路径是可访问的,在父位置读取将失败 完全。
也...
.read和.write规则从上到下工作,规则较浅 压倒更深层的规则。
这意味着您必须直接为 Messages 父节点定义某种读取规则。但是,此规则将覆盖相应子节点的规则。
希望这有帮助!