构建基于 Firebase 的数据的最佳方法是什么?

我对 Firebase 还是个新手,我想知道构建数据库的最佳方法是什么。

我有一个简单的例子:

我的项目有申请人和应用程序。1个申请人可以有多个申请。我怎样才能把这两件东西联系起来呢?它像关系数据库一样工作吗?或者在数据设计方面需要完全不同的方法?

58561 次浏览

Firebase 非常像关系数据库。如果你想把它和其他东西比较,我会把它和分层数据库比较。

Anant 最近在 Firebase 的博客上写了一篇关于反规范化数据的文章: https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html

我确实建议将每个申请的“ ID”作为每个申请人的子女保留。

更新 : 现在有了一个 关于结构化数据的文献

与 RDBMS 相反,分层数据的主要问题是,嵌套数据很诱人,因为我们可以。通常,尽管缺少连接语句和查询,但您希望在一定程度上规范化数据(就像使用 SQL 一样)。

您还希望在读取效率是一个问题的地方使用 denormalize。这是所有大型应用程序(如 Twitter 和 Facebook)都使用的一种技术,尽管它违背了我们的 DRY 原则,但它通常是可伸缩应用程序的一个必要特性。

这里的要点是,你要努力写作,使阅读容易。保持逻辑组件分开阅读(例如,对于聊天室,不要把消息、关于聊天室的元信息和成员列表都放在同一个地方,如果你想以后能够迭代这些组)。

The primary difference between Firebase's real-time data and a SQL environment is querying data. There's no simple way to say "SELECT USERS WHERE X = Y", because of the real-time nature of the data (it's constantly changing, sharding, reconciling, etc, which requires a simpler internal model to keep the synchronized clients in check)

A simple example will probably set you in the right state of mind, so here goes:

/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets

Now, since we're in a hierarchical structure, if I want to iterate users' email addresses, I do something like this:

// 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));

这种方法的问题在于,我刚刚强制客户机下载了所有用户的 messageswidgets。如果这些东西都没有成千上万,那也没什么大不了的。但是对于10000用户和每个5000消息以上的用户来说,这是一件大事。

因此,现在分层实时结构的最佳策略变得更加明显:

/user_meta/uid/email
/messages/uid/...
/widgets/uid/...

在这个环境中非常有用的另一个工具是索引。通过创建具有某些属性的用户索引,我可以通过简单迭代索引来快速模拟 SQL 查询:

/users_with_gmail_accounts/uid/email

Now if I want to, say, get messages for gmail users, I can do something like this:

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 文章 所以也看看这些中提供了一些细节。我看到弗兰克已经发表了阿南特的文章,所以我不会在这里重申,但它也是一个伟大的阅读。

在关系世界中,您的场景看起来像是一对多,因为根据您的示例,应用程序有许多应用程序。如果我们来到火场鼻子的方式,它看起来像下面。它应该在没有任何性能问题的情况下进行扩展。这就是为什么我们需要反规范化,如下所述。

applicants:{
applicant1:{
.
.
applications:{
application1:true,
application3:true
}
},
applicant2:{
.
.
applications:{
application2:true,
application4:true
}
}}


applications:{
application1:{
.
.
},
application2:{
.
.
},
application3:{
.
.
},
application4:{
.
.
}}