我希望将Firebase(和AngularJS)用于包含不同类型活动的音乐节网站。我是分层次设计数据结构的新手,并已阅读Stackoverflow和firebase博客上的许多引用,这些都有助于引导我解决这个问题。
这个音乐节有音乐活动,电影活动,讲座活动等,所有这些都有一些重叠的属性(名称,日期,描述),但也有不同的属性,具体取决于事件类型。根据我在Firebase中构建数据的知识,我到目前为止考虑了两个模型:
ROOT | +--EVENTS | +-- EventID_1 | |-- EventType: "Music" | |-- Name: "The Beatles" | |-- Description: "Description goes here." | |-- Date: "2012-04-23T18:25:43.511Z" | |-- Mp3Url: "http://some.music.url" | |-- OtherMusicOnlyAttrib: "..." | +-- EventID_2 | |-- EventType: "Movie" | |-- Name: "A Light That Never Goes Out" | |-- Description: "Description goes here." | |-- Date: "2012-04-23T18:25:43.511Z" | |-- YouTubePreview: "http://youtube.com/somevideo" | |-- OtherMovieOnlyAttrib: "..." | +-- EventID_3 |-- EventType: "Lecture" |-- Name: "Cornelius Northshire" |-- Description: "Summary of lecture topic." |-- Date: "2012-04-23T18:25:43.511Z" |-- Bio: "Biography of lecturer." |-- OtherLectureOnlyAttrib: "..."
好处:此结构明显且直接的好处是所有事件都位于一个Firebase网址上。创建一次列出所有事件的主计划视图非常简单。然后我可以通过EventType
在客户端过滤仅用于音乐的视图,或者如果用户希望仅在主时间表上看到音乐或仅看电影。
缺点:拥有不对称模型感觉不对劲。我也关注客户端过滤的速度,因为可能会有大约500个条目,但也许它不会成为问题。
ROOT | +-- EVENTS | +-- MUSIC | | | +-- MusicEventID_1 | | | |-- Name: "The Beatles" | |-- Description: "Description goes here." | |-- Date: "2012-04-23T18:25:43.511Z" | |-- Mp3Url: "http://some.music.url" | |-- OtherMusicAttrib: "..." | +-- MOVIES | | | +-- MovieEventID_1 | | | |-- Name: "A Light That Never Goes Out" | |-- Description: "Description goes here." | |-- Date: "2012-04-23T18:25:43.511Z" | |-- YouTubePreview: "http://youtube.com/somevideo" | |-- OtherMovieAttrib: "..." | +-- LECTURES | +-- LectureEventID_1 | |-- Name: "Cornelius Northshire" |-- Description: "Summary of lecture topic." |-- Date: "2012-04-23T18:25:43.511Z" |-- Bio: "Biography of lecturer." |-- OtherLectureAttrib: "..."
好处:每种事件类型都有自己的Firebase网址。因此,对于仅音乐视图的客户端事件过滤将是不必要的。此外,每个事件模型对于每个项目都是一致的,这可以使显示事件详细信息视图更容易。
缺点:列出所有事件类型(可能)的主计划视图变得更加困难。我不熟悉迭代所有事件类型及其子事件的好方法,尽管我确信它是可能的。
我想在这里学到一些东西。如果有人有关于哪种方式会更好的反馈(并且我对这些更开放,"更好"意味着),我将不胜感激。当然,如果它出现,我也会对第三种选择开放。我希望以后能够阻止自己后悔这个决定。我希望沿着可以最大限度地提高灵活性的道路前进。
答案 0 :(得分:0)
我没有使用Firebird的经验(我总是在SQL Server上工作),但我认为你问的是一般的数据库设计问题。我会使用你发布的第一个选项的变体。特别是如果您需要列出事件类型。我唯一要改变的是,有一个基表(例如事件),包含所有共享属性(名称,描述,日期,事件类型等等),然后有特定事件类型属性的小表。在这些表上,您需要一个事件ID来与主事件相关联。您可以拥有一个包含事件类型的表,这样您就可以轻松添加新类型的事件。这有点去规范化,因为具有事件特定属性的表只与事件表的子集相关,但在这种情况下(我认为)最好使用这种模式。
我不明白为什么你提到作为回顾关注客户端过滤速度的原因。你不应该这样做。对于过滤器事件,您始终可以调用服务器,过滤并将过滤后的信息重新发送到客户端。
我希望它可以帮助你,让我知道我是否可以帮助你做任何事情。
答案 1 :(得分:0)
鉴于我并不完全了解您的使用案例和需求,并且仅在此处使用仿制药进行讨论,我对方法的首选将是您的平面和不对称的变体。
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 cache和pagination。
一旦我们进入每秒数百次读取/数百万条记录,还需要考虑许多优化措施;此时,在每个索引上存储一些元数据可能会很有用,因此我不必获取读取记录(例如,用true
属性替换Name
,例如)
希望有所帮助。