Firebase 数据结构和 url

Posted

技术标签:

【中文标题】Firebase 数据结构和 url【英文标题】:Firebase data structure and url 【发布时间】:2013-05-14 08:52:54 【问题描述】:

我是 Firebase 和 nosql 的新手,所以请耐心等待我使用对 sql 的引用。 所以我的问题是如何在 firebase 中构造数据?

在firebase中,这意味着mysql中的每个“新firebase”=“新数据库”还是“表”?

如果在我的实时网络应用程序中,我有用户和 cmets。 在 mysql 中,我将创建一个 users 和一个 cmets 表,然后将它们链接在一起。

如何在 firebase 中构建它?

【问题讨论】:

看来我会是第一个给你指出这个网址的人:firebase.com/blog/2013-04-12-denormalizing-is-normal.html :) @kostik 顺便问一下,你有更多关于这方面的信息吗?我的意思是关于从关系数据库背景到 nosql 的新手的文章或教程。 我也是新手 :) 我昨天花了很多时间来问这个问题***.com/questions/16628362/…,我认为这个问题没有答案。所以请记住,firebase 并非适用于所有情况 嗨@vzhen,正如 kostik 所说,Firebase 不是 SQL 数据库。它更类似于分层数据库或(可能是一个稍微简单的比喻)将元素插入 XML 文档。我建议在这里阅读对 kostik 早期问题的回复:***.com/a/16423051/209103。 【参考方案1】:

如果你有用户和 cmets,你可以像这样轻松地建模:

ROOT
 |
 +-- vzhen
 |     |
 |     +-- Vzhen's comment 1
 |     |
 |     +-- Vzhen's comment 2
 |
 +-- Frank van Puffelen
       |
       +-- Frank's comment 1
       |
       +-- Frank's comment 2

但是,更有可能存在第三方实体,例如文章,并且用​​户正在评论(彼此的)文章。

Firebase 没有外键的概念,但很容易模仿。如果这样做,您可以像这样对用户/文章/评论结构进行建模:

ROOT
 |
 +-- ARTICLES
 |     |
 |     +-- Text of article 1 (AID=1)
 |     |
 |     +-- Text of article 2 (AID=2)
 |
 +-- USERS
 |     |
 |     +-- vzhen (UID=1056201)
 |     |
 |     +-- Frank van Puffelen (UID=209103)
 |
 +-- COMMENTS
 |     |
 |     +-- Vzhen's comment on Article 1 (CID=1)
 |     |
 |     +-- Frank's response (CID=2)
 |     |
 |     +-- Frank's comment on article 2 (AID=2,UID=209103)
 |
 +-- ARTICLE_USER_COMMENT
       |
       +-- (AID=1,UID=1056201,CID=1)
       |
       +-- (AID=1,UID=209103,CID=2)
       |
       +-- (AID=2,UID=209103,CID=3)

这是您在关系数据库中建模的方式的一个非常直接的映射。此模型的主要问题是您需要进行多次查找才能获取单个屏幕所需的信息。

    阅读文章本身(来自 ARTICLES 节点) 读取有关 cmets 的信息(来自 ARTICLE_USER_COMMENT 节点) 读取 cmets 的内容(从 COMMENTS 节点)

根据您的需要,您甚至可能还需要读取 USERS 节点。

请记住,Firebase 没有 WHERE 子句的概念,该子句允许您从 ARTICLE_USER_COMMENT 中仅选择与特定文章或特定用户匹配的元素。

在实践中,这种映射结构的方式是不可用的。 Firebase 是一种分层数据结构,因此我们应该使用为我们提供的独特功能,而不是更传统的关系模型。例如:我们不需要 ARTICLE_USER_COMMENT 节点,我们可以直接在每篇文章、用户和评论本身下保存这些信息。

这个小sn-p:

ROOT
 |
 +-- ARTICLES
 |     |
 |     +-- Text of article 1 (AID=1)
 |     .    |
 |     .    +-- (CID=1,UID=1056201)
 |     .    |
 |          +-- (CID=2,UID=209103)
 |
 +-- USERS
 |     |
 |     +-- vzhen (UID=1056201)
 |     .    |
 |     .    +-- (AID=1,CID=1)
 |     .    
 |
 +-- COMMENTS
       |
       +-- Vzhen's comment on Article 1 (CID=1)
       |
       +-- Frank's response (CID=2)
       |
       +-- Frank's comment on article 2 (CID=3)

您可以在此处看到,我们正在将来自 ARTICLE_USER_COMMENT 的信息传播到文章和用户节点。这有点对数据进行非规范化。结果是当用户向文章添加评论时,我们需要更新多个节点。在上面的示例中,我们必须添加评论本身,然后将节点添加到相关的用户节点和文章节点。好处是当我们需要显示数据时,我们可以读取的节点更少。

如果你将这种非规范化发挥到极致,你最终会得到这样的数据结构:

ROOT
 |
 +-- ARTICLES
 |     |
 |     +-- Text of article 1 (AID=1)
 |     |    |
 |     |    +-- Vzhen's comment on Article 1 (UID=1056201)
 |     |    |
 |     |    +-- Frank's response (UID=209103)
 |     |
 |     +-- Text of article 2 (AID=2)
 |          |
 |          +-- Frank's comment on Article 2 (UID=209103)
 |
 +-- USERS
       |
       +-- vzhen (UID=1056201)
       |    |
       |    +-- Vzhen's comment on Article 1 (AID=1)
       |
       +-- Frank van Puffelen (UID=209103)
            |
            +-- Frank's response (AID=1)
            |
            +-- Frank's comment on Article 2 (AID=2)

您可以看到我们在最后一个示例中删除了 COMMENTS 和 ARTICLE_USER_COMMENT 节点。现在,关于一篇文章的所有信息都直接存储在文章节点本身下,包括该文章的 cmets(带有指向发表评论的用户的“链接”)。现在,关于用户的所有信息都存储在该用户的节点下,包括用户创建的 cmets(带有指向评论所涉及文章的“链接”)。

这个模型唯一仍然棘手的是 Firebase 没有 API 来遍历此类“链接”,因此您必须自己查找用户/文章。如果您使用 UID/AID(在此示例中)作为标识用户/文章的节点名称,这将变得容易得多。

这就是我们的最终模型:

ROOT
 |
 +-- ARTICLES
 |     |
 |     +-- AID_1
 |     |    |
 |     |    +-- Text of article 1
 |     |    |
 |     |    +-- COMMENTS
 |     |         |
 |     |         +-- Vzhen's comment on Article 1 (UID=1056201)
 |     |         |
 |     |         +-- Frank's response (UID=209103)
 |     |
 |     +-- AID_2
 |          |
 |          +-- Text of article 2
 |          |
 |          +-- COMMENTS
 |               |
 |               +-- Frank's comment on Article 2 (UID=209103)
 |
 +-- USERS
       |
       +-- UID_1056201
       |    |
       |    +-- vzhen
       |    |
       |    +-- COMMENTS
       |         |
       |         +-- Vzhen's comment on Article 1 (AID=1)
       |
       +-- UID_209103
            |
            +-- Frank van Puffelen
            |
            +-- COMMENTS
                 |
                 +-- Frank's response (AID=1)
                 |
                 +-- Frank's comment on Article 2 (AID=2)

我希望这有助于理解分层数据建模和所涉及的权衡。

【讨论】:

很好的答案,谢谢。我在这里有一些问题。在最终模型中,您的意思是如果vzhenarticle(AID_1) 发表评论,那么我必须将评论插入两个节点(articles and users) 对吗?那么这会成为重复数据吗? 另一个问题是,如果我想找出vzhen发布的所有文章,那意味着我必须做同样的事情,比如cmets在vzhen_uid下创建一个articles子节点? 我可以这样说吗?在关系数据库中,我们创建空间来存储我们的数据,然后使用JOIN 来获取数据的外观。在分层数据库中,我们必须在为它们创建空间之前知道数据的样子。 @vzhen:确实,您必须在多个位置插入评论。像这样对数据进行非规范化会使您的插入/更新更加复杂(并且通常更慢)。但是,它可以简化您的读取操作,因此如果您希望读取量大大超过写入量,这是一个有用的策略。 Firebase 在他们的文档中提供了一些指导,如果您正在学习构建数据,这些指导可能会有所帮助:firebase.com/docs/web/guide/understanding-data.html 和 firebase.com/docs/web/guide/structuring-data.html 当您需要为每条评论加载用户信息时,您是否会再次读取每条评论以获取用户最新的节点数据?例如,如果用户更改了他们的名字。

以上是关于Firebase 数据结构和 url的主要内容,如果未能解决你的问题,请参考以下文章

从多个文件上传 Firebase 存储中获取下载 url

Firebase 存储 URL 随新令牌不断变化

如何在实时 Firebase 数据库中保存上传图片的完美 url-link?

使用 URL (Swift) 从 Firebase 获取数据

firebase 数据库和存储为图像返回 null

如何从firebase数据库中检索url并通过UIButton(SWIFT)显示url?