我正在构建一个电子学习应用,并将学生活动显示为时间轴,我应该将它们嵌入user
集合中,还是使用userId
创建单独的集合。
约束:
我在这两个问题中找到了相关问题的不同模式:
try and embed as much as possible
don't bloat a collection, because querying the elements deep below might be hard, especially if you're going to use lists
答案 0 :(得分:1)
这两篇文章都是正确的,都是错误的。
嵌入还是不嵌入?这始终是关键问题,它取决于您的需求,查询和存储,甚至是您的工作集。
在一天结束时,我们只能指出你实际上无法告诉你哪一个最好。
但是,考虑到活动源的大小,我个人不会嵌入它,因为它可以很容易地超过16meg(每个用户)但是对于查询的速度和功能,你可以聚合,比如说,用户的最后20个活动然后将其嵌入到用户行中(因为最后20个通常是最常查询的内容)。
但是然后嵌入聚合依赖,分片可以负责查询大量水平缩放的集合,并且使用正确的查询意味着你没有从嵌入中获得任何实际好处,并且可以通过维护索引来便利地使你的生活变得更加困难,维护该子文档所需的存储和查询。
至于嵌入死亡点。目前很多MongoDB查询主要依赖于一个或两个级别的嵌入,这就是为什么难以维护12个嵌套表格,此时你开始在这里看到问题以及谷歌集团如何维护这样的问题一个巨大的文件(如果你真的想答案,答案就是客户方。)
在90%的情况下,我们一次只需要看一个用户,另一个案例是主管(教师)需要查看用户活动摘要(可能是另一个收藏?)
考虑到这一点,我会在用户上设置一个聚合,这意味着用户可以通过一次往返看到自己或其他用户活动。
然而,考虑到教师必须最有可能拥有所有用户的页面结果,我会为他们提供单独的活动集合和查询。分页聚合文档需要一些查询,在这种情况下,最好这样做。
希望这能让你开始。
答案 1 :(得分:1)
您不应将活动嵌入学生档案中。
我对此非常有信心的原因如下:
“用户活动详细且数量众多”
“将学生活动显示为时间表”
“教师需要查看用户活动的摘要”
设计具有不断增长的文档的模式是一种不好的做法 - 因此,让学生文档在每次完成/添加其他活动时不断增长都会导致性能不佳。
如果您想对学生的活动进行排序,如果每个活动集合中的单独文档都比学生文档中的数组更加简单,则会更加简单。
当您需要查询多个学生的活动时,将所有活动放在一个集合中会使其变得微不足道,但是在学生文档中嵌入活动会使其变得困难(您将需要聚合框架,这很可能会使其变慢)。
你还说你将来可能需要“看看谁先完成了一些特定的活动?但是这种关系会改变为多对多,这是一个完全不同的问题” - 事实并非如此。您不需要将其视为多对多关系 - 您仍然可以存储与单个用户关联的多个活动,然后查询匹配活动“X”的所有记录按时间排序(或其他)排序并查看哪个学生时间最短。