4

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

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

我对如何管理这些关系感到困惑。比如article-comments模型,是不是直接把所有的评论都存到article模型中,然后每次都把整个article对象读成JSON?但是,如果评论变得非常大怎么办?比如一个文章对象有1000条评论,这样的策略会不会每次都让GET过程变得很慢?

4

4 回答 4

1

我绝不是这方面的专家,但是我以前经历过类似的情况。

从我看到的几个演示中,是的,您应该直接将所有评论存储在行中。这将为您提供最佳性能(除非您期待一些荒谬的评论)。这样您就可以在文档中拥有所有内容。

将来,如果事情开始进展顺利并且您确实注意到事情进展缓慢,您可以做一些事情。您可以参考存储其他评论的位置来存储最新(插入任意数量)评论,然后将旧评论映射到“桶”中以保持快速加载时间。

但是最初我会将其存储在一个文档中。

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

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

如果您确实将评论从您的评论字符串中移出,那么只有 oldCommentsIdentifier 才会被填充,但是我真的不会为少于 1000 条甚至更多的评论这样做。需要在这里进行一些测试,看看“甜蜜”点是什么。

于 2012-12-05T22:14:59.517 回答
0

我认为答案的很大一部分取决于您期待多少评论。拥有一个包含可能增长到任意大大小的数组的文档是一个坏主意,原因有几个。首先,$push操作员往往很慢,因为它经常增加文档的大小,迫使它被移动。其次,最大 BSON 大小为 16MB,因此最终您将无法再扩大阵列。

如果您希望每篇文章都有大量评论,您可以创建一个单独的“comments”集合,其中每个文档都有一个“article_id”字段,其中包含它所关联的文章的 _id(或 uid,或文章独有的其他一些领域)。这将使检索特定文章的所有评论变得容易,方法是查询“article_id”字段与文章_id匹配的任何文档的“comments”集合。索引该字段将使查询非常快。

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

于 2012-12-05T22:33:14.763 回答
0

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

并非如此,NoSQL 不仅仅是嵌入模型。应针对您的场景仔细考虑事实嵌入。

聚合框架确实解决了很多问题,这些问题可以通过嵌入需要用作文档本身的对象来解决。我将需要用作文档的子文档定义为:

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

正如我所说,聚合框架确实解决了这个问题,但是您仍然在考虑实时或接近执行查询,这很像在 SQL 中对相同数量的文档执行相同的查询。

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

您可以使用 $slice 运算符通过正常查询来实现分页(某种)分页,但这可能会包含与使用skip()limit()处理大型结果集几乎相同的问题,这也是不可取的,因为您无法使用范围查询(将再次需要聚合框架)。即使有 1000 个子文档,我也看到了速度问题,不仅是我自己,其他人也有。

那么让我们回到最初的问题:如何管理模式。

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

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

于 2012-12-06T08:33:45.593 回答
0

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

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

在一种情况下嵌入不起作用。据我所知,MongoDB 中的文档大小限制为 16 MB。这实际上是相当大的。但是,如果您认为您的文档大小可以超过此限制,最好单独收集。

于 2012-12-06T09:31:03.807 回答