Mongodb设计,嵌入与关系

时间:2010-09-28 14:47:05

标签: mongodb mongoid nosql

我正在建立一个简单的会计系统,用户有很多账单。现在,我正在尝试决定账单应该是自己的集合,还是嵌套在用户中。我倾向于前者,但我从来没有做过任何noSQL的东西,所以我只是通过反复试验和我认为对我有意义。

据我所知,Mongo有一个4mb的文件大小限制,这让我觉得我应该有一个单独的账单收集,因为这些将每天累积,最终可能占用大量空间。

我只是在寻找有关此事的意见。基本上我会查询不同日期之间的用户账单(你可以想象一个会计系统会这样做)。

这并不重要,但我在Rails3项目中使用Mongoid。我想我会做类似的事情:

class User
  references_many :bills
end

class Bill
  referenced_in :user
end

非常感谢任何评论或设计建议。

3 个答案:

答案 0 :(得分:24)

1)关于4MB文件限制,这就是“MongoDB:The Definitive Guide”所说的:

  

大于4MB的文档(转换为BSON时)无法保存到数据库中。这是一个有点武断的限制(将来可能会提出);它主要是为了防止错误的架构设计并确保一致的性能。要查看文档 doc 的BSON大小(以字节为单位),请从shell运行Object.bsonsize( doc )。

     

为了让您了解4MB的数量, War and Peace 的整个文本只有3.14MB。

最终,它取决于您对用户账单增长的预期程度。我希望上面的摘录能让您了解文档大小所带来的限制。

2)如果你知道你永远不会在账单上运行全局查询,那么去规范化的模式(账单与用户文档一起使用)是可行的方法(例如,如果你想检索十条最近的账单输入系统)。如果使用非规范化模式,则必须使用map-reduce来检索此类查询的结果。

如果您希望灵活地查询账单,则规范化架构(单独文档中的用户和账单)是更好的选择。但是,由于MongoDB不支持连接,因此每次要检索与用户对应的帐单时,都必须运行多个查询。

鉴于您提到的用例,我将使用非规范化架构。

3)MongoDB中的所有更新都是原子的和序列化的。这应该回答史蒂夫的担忧。

您可能会发现这些幻灯片很有帮助。 http://www.slideshare.net/kbanker/mongodb-meetup

您还可以查看MongoDB的Production Deployments页面。您可能会发现SF.net幻灯片很有用。

答案 1 :(得分:1)

您可能想要考虑的一个问题是,除了用户的成员资格之外,您是否还需要单独引用账单?如果是这样的话,如果他们有独立存在就会更简单。

除此之外,您已经确定的大小限制问题是将它们分开的一个很好的理由。

也可能存在交易问题,如果您正在编写包含许多附加账单的大型用户,如果您从不同的连接中合理地同时写入对同一用户的更改,会发生什么?我不太了解mongo知道如何解决这个问题 - 我的猜测是,如果写入包含不同的附加账单,你会得到它们两个,但如果它们包含现有账单的不同变化,你会被覆盖 - 希望其他人会对此发表评论,但至少我会测试它。如果您将账单写入单独的集合,这不是一个问题。

答案 2 :(得分:1)

自从这个问题得到解决已经很久了,但是我正在处理类似的事情,并认为我会将其研究结果添加到研究此问题的其他人。

我的理解是,在1.8+版本中,4MB文档已扩展到16MB。这是来自Banker的视频演示,他是MongoDB成员之一。我没有证实这个价值,但我正在接受他的话(因为他希望知道他在说什么)。

关于在具有嵌入式账单的同一用户上发生多次更新时会发生什么的问题...再次来自同一视频演示,提供的答案是MongoDB如此快速地更新信息,通常不是问题。在更新发生时,MongoDB实例被锁定,因此多个更新不应成为问题。

我对嵌入式文档的一个担忧是它们无法独立于父文档处理。在我看来,这使嵌入式文档变得毫无价值。它们仅适用于满足特定用例的小众案例。

我个人发现MongoDB(和NoSQL DB)对特定情况很有用,但传统的SQL / RDMS对于大多数问题仍然更好。如果您是像Craigslist这样的人,并且模式更改需要2个月的时间来运行您的归档数据,那么是的,MongoDB和NoSQL是有道理的。但对于绝大多数应用程序,我认为处理大量数据并不是一个主要问题。