mongoDB处理1-n n-n关系的最佳实践是什么?

时间:2012-12-05 22:07:15

标签: node.js mongodb

在关系数据库中,1-n n-n关系表示2个或更多表。 但是在mongoDB中,因为可以将这些东西直接存储到这样的模型中:

Article{
  content: String, 
  uid: String,
  comments:[Comment]
}

我对如何管理这些关系感到困惑。例如,在article-comments模型中,我应该直接将所有注释存储到文章模型中,然后每次将整个文章对象读出到JSON中吗?但如果评论变得非常大,该怎么办?就像文章对象中有1000条评论一样,这样的策略会不会每次都使GET过程变得非常慢?

4 个答案:

答案 0 :(得分:1)

我绝不是这方面的专家,但我之前已经解决过类似情况。

从我看过的几个演示中你应该直接存储所有评论。这将给你最好的表现(除非你期待一些荒谬的评论)。通过这种方式,您可以获得文档中的所有内容。

将来如果事情开始变得很好并且你注意到事情变得越来越慢,你可以做一些事情。您可以查看存储最新(插入任意数量)的注释,并参考其他注释的存储位置,然后将旧注释映射到"存储桶中。保持加载时间快。

但最初我将它存储在一个文档中。

所以会有一个看起来像这样的模型:

Article{    
    content: String, 
    uid: String,
    comments:[
        {"comment":"hi", "user":"jack"},
        {"comment":"hi", "user":"jack"},
    ]
    "oldCommentsIdentifier":12345
}

然后只有你的注释字符串中移出了注释才会填充oldCommentsIdentifier,但是我真的不会为少于1000条注释甚至更多注释执行此操作。这里需要进行一些测试才能看到" sweet"现场将是。

答案 1 :(得分:0)

我认为答案的很大一部分取决于您期望的评论数量。由于一些原因,拥有包含可能增长到任意大尺寸的阵列的文档是一个坏主意。首先,$push运算符往往很慢,因为它经常会增加文档的大小,迫使它被移动。其次,最大BSON大小为16MB,因此最终你将无法再增加阵列。

如果您希望每篇文章都有大量的评论,您可以创建一个单独的“评论”集合,其中每个文档都有一个“article_id”字段,其中包含与之关联的文章的_id(或者uid,或文章特有的其他一些领域)。这样可以通过查询“comments_id”字段与文章的_id匹配的任何文档的“comments”集合,轻松检索特定文章的所有评论。索引此字段会使查询速度非常快。

作为对您的问题的评论发布的关联的链接也是关于架构设计的一般提示的一个很好的参考。

答案 2 :(得分:0)

  

但是如果通过将文章和评论与_id链接来解决这个问题,那么它是否会回到关系数据库设计?并且不知何故失去了NoSQL的本质?

不是真的,NoSQL不仅仅是嵌入模型。对于您的场景,应该仔细考虑事实嵌入。

聚合框架确实解决了嵌入您需要用作文档本身的对象所带来的一些问题。我定义需要用作文档的子文档:

  • 需要在界面中分页的文档
  • 多个根文档中可能存在的文档
  • 需要在其群组内进行高级排序的文档
  • 组中的文件超过根文件16meg限制

正如我所说,聚合框架确实解决了这个问题,但是你仍然在寻找一个实时或接近的查询,就像在相同数量的文档中在SQL中执行相同的操作一样。

这种效果并不总是可取的。

您可以使用$ slice运算符进行正常查询,从而实现子查询的分页(排序),但这样可以解决与在大型结果集上使用skip()limit()几乎相同的问题,这也是不受欢迎的,因为您无法使用范围查询轻松修复它(再次需要聚合框架)。即使有1000个子文档,我也看到了速度问题,不仅仅是我,还有其他人。

让我们回到最初的问题:如何管理架构。

现在你不喜欢的答案是:这一切都取决于。

您的意见是否满足他们应该分开的需求?那么这可能是一个不错的选择。

答案 3 :(得分:0)

没有最好的办法。在MongoDB中,您应该根据将要使用它的应用程序来设计您的集合。

如果您的应用程序需要在文章中显示评论,那么我可以说最好将这些评论嵌入文章集合中。否则,您最终将数次往返数据库。

有一种情况是嵌入不起作用。据我所知,MongoDB中的文档大小限制为16 MB。这实际上非常大。但是,如果您认为文档大小超出此限制,则最好单独收集。