MongoDB非规范化“向下”而不是嵌入

时间:2014-08-15 10:45:35

标签: mongodb mongodb-query

这是我第一次真正涉足NoSQL,并且来自传统的RDBMS背景,我很难理解非规范化数据。我读过的大多数文章/书籍总是归结为Embed or Reference。但是我想知道将一个父元素带入子节点而没有嵌入的用例是多么常见。

作为一个例子,考虑我有以下两个文件,这是一个艺术家正在做的巡回演出和他们正在演奏的个人演出(这将使用参考):

Tour:
  "artist": string,
  "genre": [string],
  "info": string
  "venue": {
    "name": string,
    "address": string
  }

Gig:
  "date": date,
  "tourId": string,
  "availableTickets": number
  "price": number

这些数据将来自众多不同的来源并写入MongoDB,然后进行查询。此应用程序最重要的因素是读取性能。

最初我考虑过在游戏中嵌入Gig,但是一些Tours会有1或2个Gigs,其他的将有100多个,这样就会产生大小不同的文档,这些文档可以以不同的速率增长。

然后我查看了相关(使用上述结构)但这使得一些查询很难回答,因为我不得不搜索两个集合。像

这样的东西
  • “哪个演出是Pink Floyd在八月播放,至少有4张门票少于50”
  • “明年1月在伦敦举办任何日间爵士音乐会”

然后我考虑将Tour中的一些字段带入Gig(例如艺术家,流派和场地名称),这样就可以通过查看Gig系列来回答上述问题。

这显然会导致大量冗余数据。例如普林斯在巡回演出中有400场演出,类型/艺术家等将会重复。如果他重新命名自己(我再次),我需要更新所有这些需要时间的事情。

由于Reads的表现肯定更重要,我正在考虑采用这种模式 - 是否有人对此有任何经验/警告的话?我是否过早地注销了数据?文件大小的差异以及演出需要自己访问的事实让我回避嵌入,但我想知道不经常更新Tours的维护开销是否太多。

1 个答案:

答案 0 :(得分:1)

我认为将父母关于儿童的信息非规范化是一种模式设计技术,这种技术被大大少用,并且听起来非常适合您的用例。一种自然而常见的方法是为父母存储一系列孩子(或者父母有一个孩子的对象,其中密钥是可变的,而且是先验未知的值 - 呀!)。这有一些我能想到的缺点:

  • 难以阅读的个别孩子
  • 难以更新子项的逻辑组,无论是属于同一父级还是属于多个父级
  • 如果子项数量变得非常大或经常更新,导致文档增长和磁盘移动,则可伸缩性问题

将父母的数据归一化到孩子中解决了上述问题,明显的缺点是父子的数据在其所有孩子中重复,导致更新父信息的难度增加。重复数据的想法最初让人感到害怕,但我认为阅读量大的应用程序的优势远远超过了成本。偶尔更新400个文档以换取躲避多个查询,客户端操作或额外的聚合操作以实现正常读取是一种胜利。

还有一种混合方法,其中您的文档代表GigTour的核心Gig信息,但也引用另一个Tour集合在Gig中查询有关Tour的信息时,包含不常需要的信息的文档。