【问题标题】:Firebase Structure: Flat and Asymmetical or Break OutFirebase 结构:扁平且不对称或突围
【发布时间】:2014-05-21 02:09:41
【问题描述】:

我希望将 Firebase(和 AngularJS)用于包含不同类型活动的音乐节网站。我是分层设计数据结构的新手,并且已经阅读了 Stackoverflow 和 firebase 博客上的许多入门书,这对我提出这个问题很有帮助。

这个音乐节有音乐活动、电影活动、讲座活动等,所有这些活动都有一些重叠的属性(名称、日期、描述),但根据活动类型的不同,它们也会有不同的属性。根据我对在 Firebase 中构建数据的了解,我目前正在考虑两种模型:

模型 1 - 平坦且不对称:

根 | +--活动 | +-- 事件ID_1 | |-- 事件类型:“音乐” | |-- 名称:“披头士” | |-- 描述:“描述在这里。” | |-- 日期:“2012-04-23T18:25:43.511Z” | |-- Mp3Url: "http://some.music.url" | |-- OtherMusicOnlyAttrib: "..." | +-- 事件ID_2 | |-- 事件类型:“电影” | |-- 名称:《永不熄灭的光》 | |-- 描述:“描述在这里。” | |-- 日期:“2012-04-23T18:25:43.511Z” | |-- YouTube 预览:“http://youtube.com/somevideo” | |-- OtherMovieOnlyAttrib: "..." | +-- 事件ID_3 |-- 事件类型:“讲座” |-- 名称:“科尼利厄斯·北郡” |-- 描述:“讲座主题摘要。” |-- 日期:“2012-04-23T18:25:43.511Z” |-- 简历:“讲师传记”。 |-- OtherLectureOnlyAttrib: "..."

好处:这种结构的明显和直接好处是所有事件都位于一个 Firebase URL。创建一次列出所有事件的主计划视图是相当简单的。然后,我可以在客户端通过 EventType 进行过滤,以获得仅音乐视图,或者如果用户希望仅查看主时间表上的音乐或电影。

缺点:不对称模型让人感觉有些不对劲。我也有点担心客户端的过滤速度,因为可能会有大约 500 个条目,但也许不会有问题。

模型 2 - 中断:

根 | +-- 活动 | +-- 音乐 | | | +-- MusicEventID_1 | | | |-- 名称:“披头士” | |-- 描述:“描述在这里。” | |-- 日期:“2012-04-23T18:25:43.511Z” | |-- Mp3Url: "http://some.music.url" | |-- 其他音乐属性:“...” | +-- 电影 | | | +-- 电影事件ID_1 | | | |-- 名称:《永不熄灭的光》 | |-- 描述:“描述在这里。” | |-- 日期:“2012-04-23T18:25:43.511Z” | |-- YouTube 预览:“http://youtube.com/somevideo” | |-- 其他电影属性:“...” | +-- 讲座 | +-- LectureEventID_1 | |-- 名称:“科尼利厄斯·北郡” |-- 描述:“讲座主题摘要。” |-- 日期:“2012-04-23T18:25:43.511Z” |-- 简历:“讲师传记”。 |-- OtherLectureAttrib: "..."

好处:每种事件类型都有自己的 Firebase url。因此,不需要对仅音乐视图进行客户端事件过滤。此外,每个事件模型对于每个项目都是一致的,这可能会使显示事件详细信息视图稍微容易一些。

缺点:列出所有事件类型(可能)的主日程表视图变得更加困难。我不熟悉迭代所有事件类型及其子事件的好方法,尽管我确信这是可能的。

结论:

我想在这里学习一些东西。如果有人对哪种方式更好有反馈(我对“更好”的含义持开放态度),我将不胜感激。当然,如果它出现,我也愿意接受第三种选择。我希望以后不会后悔这个决定。我希望能走上最灵活的道路。

【问题讨论】:

    标签: firebase


    【解决方案1】:

    我没有使用 Firebird 的经验(我总是在 SQL Server 上工作),但我认为您问的是一般数据库设计问题。我会使用您发布的第一个选项的变体。特别是如果您需要列出跨类型的事件。我唯一要改变的是有一个包含所有共享属性(名称、描述、日期、EventType 等)的基表(例如事件),然后有一个用于特定事件类型属性的小表。在这些表上,您需要一个事件 ID 与主事件相关联。您可以拥有一个包含事件类型的表格,这样您就可以轻松添加新类型的事件。这有点反规范化,因为具有事件特定属性的表仅与事件表的一个子集相关,但在这种情况下(我认为)最好使用这种模式。

    我不明白你为什么提到客户端过滤速度的缺点。你不应该那样做。对于过滤事件,您可以随时调用服务器,过滤并将过滤后的信息重新发送给客户端。

    希望对您有所帮助,如果我能帮助您解决其他问题,请告诉我。

    【讨论】:

    • 埃里克,感谢您的回答。 Firebase 可能更类似于 NoSQL 而不是 SQL。它具有分层数据结构,而不是传统的关系型 SQL DB。如果您对关键差异感兴趣,请查看Denormalizing Your Data is Normal。尽管您所说的可能有些道理,但我将暂缓给出更针对 Firebase 的答案,因为它与 SQL 完全不同。
    【解决方案2】:

    鉴于我不完全了解您的用例和需求,并且在这里只讨论泛型,我的首选方法将是您的平面和不对称的变体。

    NoSQL 与 SQL 的不同之处在于它允许创建嵌套层次结构,但是当我在大多数情况下坚持一个相当扁平的结构时,我很幸运,并且像我期望的 SQL 那样索引事物。

    例子:

    /events/$event_id/ (type, name, etc)
    /index/by_type/<music|movies|lectures>/$event_id/true
    /index/recent/$event_id/true
    

    对于recent 索引,我将按Date 对记录进行优先排序,这样我就可以使用recentIndexRef.endAt().limit(10) 之类的方式获取最近的X 记录。

    要从索引中获取记录列表,我可以执行以下操作:

    var fbRef = new Firebase(URL);
    
    function fetchRecentMusic(numberToFetch, callback) {
       var idxRef = fbRef.child('index/by_type/music').limit(numberToFetch);
       idxRef.once('value', function(snap) {
          var results = [];
          snap.forEach(function(ss) {
             results.push(ss.val());
          });
          callback(results);
       });
    }
    

    当然,这个主题有很多变体,具体取决于这些数据的实时性以及我希望如何显示它。它还涉及其他几个高级主题,例如 normalizing records through a cachepagination

    一旦我们达到每秒数百次读取/数百万条记录,还需要考虑许多优化;那时,在每个索引上存储一些元数据可能会变得有用,这样我就不必获取记录以供读取(例如将 true 替换为 Name 属性,例如)。

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2011-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-17
      • 2017-04-22
      • 1970-01-01
      • 1970-01-01
      • 2022-09-26
      相关资源
      最近更新 更多