我的应用程序的推荐Firebase数据结构

我的应用程序的推荐Firebase数据结构,firebase,firebase-realtime-database,firebase-security,Firebase,Firebase Realtime Database,Firebase Security,问题是关于我为Firebase应用程序定义的数据结构。 它正在工作,但是,我怀疑它的效率和可扩展性 想象一个聊天应用程序,其中只有一个全局聊天室 但是,您将只看到来自与您有关系的用户的消息。 从这个意义上说,“关系”是指您共享相同的组成员资格。 以下是小组: +---------+---------+---------+ | Group A | Group B | Group C | +---------+---------+---------+ | User1 | User4 | Us

问题是关于我为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只会看到来自User5和User6的消息。 为此,每个用户的关系存储在Firebase实时数据库中,如下所示:

Friends
├── User1
│   ├── User2: true
│   ├── User3: true
│   ├── User7: true
│   └── User8: true
├── User2
    ├── User1: true
    └── User3: true
等等。出于演示目的,我在这里使用用户名,实际上,这些是Firebase UID。 显然,这需要向数据库中写入大量(每个用户组)条目。 每个组的可能组数和用户数是无限的。 这些消息被添加到Firebase中,如下所示:

Messages
├── User1
│   ├── timestamp
│   │   └── message: "This is a message"
│   ├── timestamp
│   │   └── message: "This is another message"
├── User2
    ├── timestamp
    │   └── message: "..."
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安全规则可以轻松实现权限的实际强制执行:

"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)"
    }
}
这是构造数据的推荐方法吗?
我有点不确定,因为跟踪用户关系需要大量的数据。

当我们谈论效率和可扩展性时,Firebase中最重要的规则是让数据尽可能平坦。根据此规则,我建议您按照以下方式重新构建数据库:

Messages
├── User1
│   ├── timestamp
│   │   └── message: "This is a message"
│   ├── timestamp
│   │   └── message: "This is another message"
├── User2
    ├── timestamp
    │   └── message: "..."
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/
。用户所在的所有组:
firebase url/users/userId/groups/
以及来自单个组的所有消息:
firebase url/groupId\u 1/

要了解有关正确构建Firebase数据库的更多信息,请阅读此内容


希望能有所帮助。

很抱歉让您失望,但不幸的是,您无法将此数据结构用于您想要实现的目标

首先,只要组中没有太多用户,数据树的性能就应该良好。我通过重建您概述的数据结构,在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实时数据库中禁止/不可能使用数据库规则进行过滤

规则不是过滤器

规则是以原子的方式应用的。这意味着读或写 如果该位置没有规则,操作将立即失败 或者在授予访问权限的父位置。即使每个人都受到影响 子路径可访问,在父位置读取将失败 完全是

还有

.读写规则自上而下,使用较浅的规则 超越更深层次的规则

这意味着您必须直接为消息父节点定义某种读取规则。但该规则将覆盖相应子节点的规则


希望这有帮助

我感谢您的回复,并同意这是典型聊天应用程序的首选结构。然而,在我的示例中,只有一个全局聊天室,没有必要按组跟踪消息。正如您确认的,最重要的方面是保持数据尽可能平坦,我觉得我目前的结构走上了正确的轨道。我真正担心的是可伸缩性方面,例如,当有1000名用户加入一个新用户组时。正如您所说,这是典型聊天应用程序的首选数据库结构。因此,在您的情况下,不要使用
部分。在可扩展性方面,使用这种结构不会带来麻烦。我还建议你尝试一个真实的案例场景。以编程方式生成1000个用户。成为第1001个用户,看看会发生什么。所以,祝你好运,随时通知我!;)一切都好吗?我能帮你了解其他信息吗?