【问题标题】:MongoDB - One Collection Using IndexesMongoDB - 一个使用索引的集合
【发布时间】:2012-03-22 09:09:02
【问题描述】:

好吧,所以我在 Mongodb 中开发得越来越多,我开始怀疑是否需要多个集合而不是拥有一个带有索引的大型集合(因为与表格数据不同,每个文档的列和字段可能不同)。如果我试图以最有效的方式进行开发(意味着更少的代码和可重用的代码),那么我可以为所有文档使用一个集合并仅在一个字段上建立索引。通过将所有文档放在一个带有索引的集合中,我可以重用我的所有表单处理代码和其他代码,因为它们都将插入到同一个集合中。

例如:

假设我正在开发一个联系人管理器,我有两种类型的联系人“个人”和“企业”。我最初的想法是创建一个称为个人的集合和第二个称为企业的集合。但那是因为我习惯于在 sql 中开发,是的,这将是合适的,因为每个表的列都会不同。我越是开始考虑文档数据库的灵活性,我就越开始思考,“我真的需要两个集合吗?”如果我只是在每个文档中添加一个名为“联系人类型”的字段并为其编制索引,我真的需要两个集合吗?由于每个文档中的字段/列不必对所有人都相同(就像在 sql 中一样),所以每个文档都可以有自己的字段,只要我有一个“文档类型”字段和该字段上的索引。

然后我接受了这个概念并开始思考,如果我只需要一个用于“个人”和“企业”的集合,那么我什至需要一个单独的集合来存储“用户”或“联系历史”或任何其他数据。理论上,我不能在一次集合中构建整个解决方案,并且在每个文档中都有一个字段来指定“类型”和索引,例如“用户”、“个人联系人”、“业务联系人”、“联系人历史记录” ”等,如果它是与另一个文档相关的文档,我可以在“父键/外来”Id 字段上建立索引...

这将允许我对前端进行动态编码,因为表单处理代码都是相同的(插入到同一个集合中)。这将节省大量编码,但我想通过使用索引和二级索引来确保数据库仍然可以快速运行,并且不会随着集合的增长而导致未来的问题。可以想象,如果所有内容都在一个集合中,随着用户群的增长,该集合中可能会有数十万甚至数百万个文档,但它会有索引和二级索引来优化性能。

我的问题是:这是 mongodb 开发人员常用的方法吗?为什么或者为什么不?如果有的话,有哪些缺点?如果这是一种常用的方法,也请对使用此方法给予任何肯定。谢谢。

【问题讨论】:

    标签: mongodb collections indexing


    【解决方案1】:

    这在 Mongo 中是一个非常重要的观点,答案是艺术而不是科学。拥有一个充满巨大文档的集合绝对是一种反模式,因为它与 Mongo 的许多功能相悖。

    例如,在检索文档时,您只能从集合中检索整个文档(不完全正确,但大多数情况下)。因此,如果您有大量文档,那么您每次都在检索大量文档。此外,拥有庞大的文档会降低分片的灵活性,因为在每个集合中只有顶级文档被索引(因此,被分片)。您可以将值索引到文档的深处,但索引值与顶级文档相关联。

    同时,纯粹的关系型也是一种反模式,因为一开始使用 Mongo 就失去了很多参照完整性。此外,所有连接都在应用程序内存中完成,因此每个连接都需要完整的往返(慢)。

    所以答案是在两者之间做点什么。在这种情况下,我认为您可能会想要一个个人收藏和一个不同的企业收藏。我这样说是因为企业似乎有足够的相关元数据,可以大量增加。 (另外,我个人与企业的关系似乎是多对多的)。但是,个人可能有一个Name 对象(具有firstlast 属性)。将 Name 设为单独的集合是个坏主意。

    来自 10gen 的一些关于架构设计的信息:http://www.mongodb.org/display/DOCS/Schema+Design

    编辑

    此外,Mongo 对事务的支持有限 - 以原子聚合的形式。当你将一个对象插入 mongo 时,整个对象要么被插入,要么不被插入。因此,您的应用程序域需要某些对象之间的一致性,您可能希望将它们保存在同一个文档/集合中。

    例如,考虑一个要求User 始终具有Name 对象(包含FirstNameLastNameMiddleInitial)的应用程序。如果以某种方式插入了User 而没有对应的Name,则数据将被视为已损坏。在 RDBMS 中,您将围绕插入 UserName 的操作包装事务。在 Mongo 中,我们确保 NameUser 在同一个文档(聚合)中以达到相同的效果。

    您的示例不太清楚,因为我不了解业务案例。确实想到的一件事是 Mongo 对继承有很好的支持。将所有用户、个人和潜在的企业放在同一个集合中可能是有意义的(取决于应用程序的建模方式)。如果一个人有很多联系人,您可能希望个人拥有一组 ID。如果您的应用程序需要您快速预览联系人,您可以考虑复制个人的一部分并存储联系人对象数组。

    如果您习惯于使用 RDBMS 思维,您可能会认为您的所有数据都必须始终保持一致。事实是,这可能并不完全正确。这种将原子聚合应用于域的概念最近已被 DDD 社区大力宣传。当您像您的业务用户一样深入查看您的域时,一致性边界应该变得清晰。

    【讨论】:

      【解决方案2】:

      MongoDB 和一般的 NoSQL 是关于反规范化数据和减少连接的。这违背了正常的 SQL 思维。

      在您的情况下,我认为您没有任何理由希望拥有单独的集合,因为它引入了不必要的复杂性和性能开销。例如,假设您想要一个按字母顺序显示所有联系人的屏幕。如果你只有一个联系人集合,那么它真的很容易,但如果你有两个集合,它就会变得更复杂。

      如果您的应用程序有多个用户存储联系人,那么我将拥有多个集合。然后,我将为每个用户收集一个集合。这使得提取用户联系人变得非常容易。

      【讨论】:

      • 是的,我会有多个用户,但即便如此,如果我只是索引集合名称和用户 ID,然后按用户的会话 ID 减少/过滤结果,我是否需要多个集合。那我还是只用一个集合??
      • 我知道 cassandra 是关于非规范化的,但许多其他的确实与 SQL 没有任何不同(在这方面)。面向文档的数据库实际上只是一种组织数据库的不同方式。在做关系模式时,mongo 也非常宽容
      猜你喜欢
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 2013-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多