Answers:
更新:现在有一个关于数据结构的文档。另外,请参见这篇有关NoSQL数据结构的优秀文章。
与RDBMS相比,分层数据的主要问题在于,由于我们可以嵌套数据,因此很容易嵌套。通常,尽管缺少join语句和查询,您还是希望在某种程度上标准化数据(就像使用SQL一样)。
您还希望在关注读取效率的地方进行非规范化。这是所有大型应用程序(例如Twitter和Facebook)使用的技术,尽管它违反了我们的DRY原则,但通常是可伸缩应用程序的必要功能。
这里的要点是您要努力进行写操作以使读操作变得容易。将分别读取的逻辑组件分开放置(例如,对于聊天室,不要将消息,有关会议室的元信息以及成员列表都放在同一位置,如果您希望以后可以迭代这些组)。
Firebase的实时数据和SQL环境之间的主要区别是查询数据。由于数据的实时性,没有简单的说法“在X = Y处选择用户”(它不断变化,分片,协调等,这需要更简单的内部模型来保持同步客户端的状态)
一个简单的示例可能会使您处于正确的心态,因此,这里是:
/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets
现在,由于我们处于分层结构中,因此如果要迭代用户的电子邮件地址,请执行以下操作:
// I could also use on('child_added') here to great success
// but this is simpler for an example
firebaseRef.child('users').once('value')
.then(userPathSnapshot => {
userPathSnapshot.forEach(
userSnap => console.log('email', userSnap.val().email)
);
})
.catch(e => console.error(e));
这种方法的问题是,我刚才强制客户端下载所有用户的messages
和widgets
太。如果这些东西都没有成千上万,那就没什么大不了了。但对于1万名用户而言,每条消息多达5千条,意义重大。
因此,现在,用于分层实时结构的最佳策略变得更加明显:
/user_meta/uid/email
/messages/uid/...
/widgets/uid/...
在此环境中非常有用的另一个工具是索引。通过创建具有某些属性的用户的索引,我可以通过简单地迭代索引来快速模拟SQL查询:
/users_with_gmail_accounts/uid/email
现在,如果我想为gmail用户获取消息,则可以执行以下操作:
var ref = firebase.database().ref('users_with_gmail_accounts');
ref.once('value').then(idx_snap => {
idx_snap.forEach(idx_entry => {
let msg = idx_entry.name() + ' has a new message!';
firebase.database().ref('messages').child(idx_entry.name())
.on(
'child_added',
ss => console.log(msg, ss.key);
);
});
})
.catch(e => console.error(e));
我在另一篇SO帖子中提供了有关非规范化数据的一些详细信息,因此也请检查一下。我看到Frank已经发布了Anant的文章,因此在这里我不再重申,但这也是一本好书。
火力地堡是非常不一样的关系数据库。如果您想将其与任何事物进行比较,我会将其与分层数据库进行比较。
Anant最近在Firebase博客上写了一篇很棒的帖子,内容涉及对数据进行非规范化:https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html
我确实建议您将每个申请的“ ID”保留为每个申请人的子代。
在关系世界中,您的方案看起来像一对多,例如您的申请者有很多申请。如果我们使用Firebase Nosql的方式,则如下所示。它应该可以扩展,而不会出现任何性能问题。这就是为什么我们需要如下所述的非规范化。
applicants:{
applicant1:{
.
.
applications:{
application1:true,
application3:true
}
},
applicant2:{
.
.
applications:{
application2:true,
application4:true
}
}}
applications:{
application1:{
.
.
},
application2:{
.
.
},
application3:{
.
.
},
application4:{
.
.
}}