【问题标题】:Basic mongodb theory基础mongodb理论
【发布时间】:2011-02-22 08:59:58
【问题描述】:

这无疑是一个愚蠢的问题,当答案指出这一切的简单明了时,我们都可以笑这是多么愚蠢,但我似乎无法深入了解关系数据库的艺术完全了解 mongodb - 无论我阅读了多少文章或观看了多少视频。

这是我的情况。我有一个可能拥有数百万用户的项目。核心功能:

  • 拥有 4 种不同类型的用户列表
  • 其中一种用户可以创建活动
  • 其他类型的用户可以申请在活动中执行(然后在申请方和组织方之间有一个请求系统来商定条款)
  • 其他用户类型可以参加活动
  • 所有用户类型都可以关注活动
  • 每个用户都可以将无限数量的图片上传到他们的“图库”

现在我会立即知道如何规范化 MySQL 数据库并加入查询以获取我需要的数据,但是 mongodb 呢?

由于所有这些信息都与用户有关,我是否只需为用户创建一个集合?我要为每个用户创建一个文档吗?该文档是否存储了与该用户相关的事件、请求和图像的所有详细信息 - 或者只是我交叉引用的这些事物的某种 id?如果不是这样,这不会复制大量数据 - 即,如果我必须为每个关注/参加/执行该事件的用户复制所有事件数据并将其放入该用户文档中(我确信情况并非如此- 但是如果没有加入,如果事件存储在另一个集合中,我如何获得“加入”用户和所有事件数据?)。图像呢?一个用户文档可以是 16mb - 但是如果我允许无限的图像并且与用户相关的所有内容都存储在一个文档中,那么单独的图像可能会比单个文档大吗?

我确定我没有理解对理解 mongodb 至关重要的内容 - 请赐教!

谢谢。

【问题讨论】:

  • 据我所知,您可以嵌入或参考其他模型。

标签: mongodb database nosql


【解决方案1】:

您可以使用 2 个不同的用户和事件集合来设计您的应用。像这样的

UserDocument Collection
    -Type
    -Details    

EventDocument Collection
    -Created By
    -EventDetail
    -AppliedUsers
         -"User A",User B"
    -AttendingUsers
         -"User C",User D"
    -FollowingUsers
         -"User E",User F"

活动文档使用Dbref 获取了所有已申请、参加和关注用户的用户 ID。

另一种方法是将经常访问的用户文档字段与 DBref 对象一起存储。这避免了对数据库的不必要的命中和在文档中存储冗余(完整的用户数据)数据。像

 EventDocument Collection
    -Created By
    -EventDetail
    -AppliedUsers
         -"User"
             - Name
             - XXX
             - DbRef to User A
    -AttendingUsers
         -"User"
             - Name
             - XXX
             - DbRef to User B

    -FollowingUsers
         -"User"
             - Name
             - XXX
             - DbRef to User C

         -"User"
             - Name
             - XXX
             - DbRef to User D

对于图像,您可以使用 GridFs。这会将大文件分成更小的块。

【讨论】:

  • 很好的解决方案,但我认为最好总是从嵌入开始。以您的架构为例,您可以快速显示已分配事件的用户,因为您需要遍历所有用户。
  • @Bugai13,但我们可以通过将频繁访问的用户字段与 DBRef 一起存储来避免这种情况。检查我的编辑
  • 是的,但这是另一个关于如何更好地对数据库进行非规范化以满足某些需求的大问题。
  • 啊哈是的,这似乎是一个很好的解决方案。我现在了解了 mongodb 如何工作的基础知识!我想我现在需要查找 mongodb 规范化/去规范化的最佳实践。谢谢!
【解决方案2】:

最初我建议只创建 UserDocument 并将所有与事件相关的集合嵌入到用户内部,将来您会看到事件是否是大集合(超过 mongodb 限制 4mb),您会将其移动到单独的集合中。至于图像,请查看 mongodb gridFs 功能,它允许您存储任意大小的文件。在用户文档中,您只能存储 fileId 的集合。

当您开始设计文档数据架构时,总是从嵌入 evething 开始,稍后您会看到您需要移动到单独的集合中。在您的情况下,如果您需要例如显示所有事件的列表,您将无法轻松做到这一点,因为您需要加载每个用户并获取嵌入的事件集合,在这种情况下需要将事件移动到单独的集合中。

更新:

因为您需要从任何用户文档中引用事件,所以您需要将事件移动到单独的集合中,因为引用嵌入的集合总是不好的。

所以在与自己讨论之后,在我看来,以下方案应该适合您的需要:

UserDocument Collection
    -UserId
    -Type
    -Details    
    -Events(EventId)
    -AppliedEvents
    -AttendingEvents
    -Files(it's not actual files it just references to gridFs filess)

EventDocument Collection
    -EventId
    -EventDetail   
    -FollowingUsers

我已经将几乎所有内容都移到了 UserDocument 中,因为 User 是一个“强大”的实体,您将更多地与用户合作而不是与事件合作(对我来说似乎如此)。

【讨论】:

  • 谢谢,这似乎也是一个不错的解决方案。请问为什么followingusers在事件文档中,而apply和ettending在用户文档中? - 感谢您阐明文件的工作方式!
  • @Colin:在事件文档中关注用户,因为我认为您需要显示事件和关注事件的用户(如果在事件内部关注用户,这很容易),但对于应用的事件,我想你应该显示用户和他应用的事件(在用户内部应用事件很容易)。
  • 4MB 的 mongodb 限制(已提高到 16MB)用于文档,而不是集合。除非您在一个文档中存储几本小说,否则 16MB 太大而不必担心。
【解决方案3】:

您应该遵循@Bugai13 和@Ramesh Vel 建议的关于您的数据库、图像和DBRefs 设计的建议。我只是想澄清几件事。

如果不是这样,这不会重复很多 数据 - 即如果我必须复制 每个用户的所有事件数据 跟随/参加/表演 事件并将其放入该用户 文件

人们在存储成本昂贵的时候提出了关系数据库的规范化 - 因此将数据拆分为多个数据并使用连接重建它们。现在存储相对来说非常便宜,如果你需要性能,数据的重复是完全不会被反对的。它确实取决于应用程序,但是,您的查询模式、您存储的数据量以及您所追求的读/写速度。但是,你会说,更多的写入(因为没有标准化)不会导致更差的性能吗?不一定,取决于应用程序。如果您对此感到担心,请查看分片(对于 MongoDB:http://www.mongodb.org/display/DOCS/Sharding+Introduction)。

但没有加入我如何获得“加入” 用户和所有事件数据(如果事件) 是否存储在另一个集合中?

还请注意,据我了解(很高兴对此进行更正),MongoDB 中没有“加入”操作。这仅发生在某些驱动程序上。正如文档所说:

DBRef 的优点是允许 可选的自动客户端 使用一些驱动程序取消引用

请注意,取消引用仅发生在客户端,并且仅发生在“某些”驱动程序中。据我所知,PHP 可以,但 Java 驱动程序没有——您必须通过从单独的集合中获取两个结果集并手动连接它们来处理应用程序级别的连接,尽管有 DBRef。

【讨论】:

  • Dbref 只是说它引用了另一个文档,仅此而已。 mongodb 中没有连接,我们可以使用“连接信息”创建新的非规范化文档,而不是连接。
  • 是的,感谢您的澄清——记住这一点非常重要。
  • 阅读 mongodb.org/display/DOCS/Schema+Design 的“嵌入 v 的参考”部分我认为这触及了您所说的 - 嵌入比引用更快。 “因此,如果我们迭代 1,000 名学生,每个学生查找一份参考资料会很慢”。因此,如果我必须嵌入的数据非常大(事件将有大量与之关联的数据,并且会在很多时候完整显示),那么引用它可能更有意义。但如果使用 mongodb 的全部目的是为了性能,那么使用关系数据库可能更有意义?
  • MongoDB 不是 RDBMS 的直接替代品。 RBMS 可以很好地解决大多数问题。如果您的问题通过 RDBMS 得到了很好的解决,那就去吧。但是,如果您看到 MongoDB 的一些优势,例如使用 MapReduce 对某些事情进行批处理,或者您觉得嵌入对您的应用程序更好,请使用 MongoDB。有人声称 MongoDB 在某些/许多情况下更快,但我不会对此进行讨论,网络上有关于此的好坏评价。请注意,在 RDBMS 中,您需要索引(=磁盘和 RAM 中的空间)来快速执行连接,因此数据复制在 MongoDB 中并不是一件坏事。
猜你喜欢
  • 2015-10-16
  • 1970-01-01
  • 2012-05-31
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
相关资源
最近更新 更多