目前,我正在使用一个小的子文档来引用其他集合:
{ name: 'xxx', id: 'xxx'}
..而不是手动参考。
所以,对于论坛帖子,我可能会这样:
{
title: 'Some title',
creator: { name: 'jgauffin', id: ObjectId(123445455) },
posts: [...]
}
原因是我每次获取文档时都不必在其他集合中进行任何查找,并且名称几乎不会改变。
但是由于我对此很陌生,是否有任何既定的设计模式?或者你是否应该对其他集合中的单个字段进行 $lookup?
快速的第一件事:“
{ name: 'xxx', id: 'xxx'}
..而不是手动参考。”ObjectId
的字段,或者您在目标集合中用作 _id
的任何类型:
手动引用是将一个 文档的
字段包含在另一个文档中的做法。然后,应用程序可以发出第二个查询来根据需要解析引用的字段。_id
另一个选项是DBRef,文档说使用手动引用,除非您需要引用多个集合。
有没有既定的设计模式?
是的,主要规则是“一起访问的数据应该存储在一起”。因此,如果您显示带有标题、用户名和个人资料链接的论坛帖子,并且这种情况经常发生,那么这是正确的选择。
如果不是直接从用户名(如
/user/<name>
)在 HTML/JS 中自动生成,或从 ObjectId
(如 /profile/<id.toString()>
)自动生成,我会添加全名(如果显示)和个人资料链接。至于处理用户更改用户名或全名,这需要在应用程序代码中完成。因此,您需要更新用户名,然后在所有受影响的集合中执行
updateMany()
:
forum_posts.updateMany(
{ creator.id: ObjectId(12345) },
{ creator.name: "newname" }
)
正如你已经说过的,“名字几乎不会改变”,这就是它的好处。
如果卷大小或事件驱动架构很大,您可以在无服务器功能或单独的后端服务中以块的形式处理这些更新。并在需要时执行
$lookup
,但避免经常需要的模式。如果正确使用,没关系不是很糟糕,只要不过度使用即可。
子文档数组:
下一部分是posts: [...]
字段。拥有无界数组是一种反模式。建议将子文档数组限制为 200 个。然后将剩余的子文档放在一个单独的集合中
more_posts
,每个集合存储 200 个。根据使用情况会有变化。您可以将
all_posts
作为 200 个大小的文档,然后将“最热门”的 50 个存储在
forum
集合中,或者最近的 20 个;当你实际使用它时。
架构根据使用情况,而不是根据数据
在 MongoDB 和其他 NoSQL DB 中,您的模式应该匹配您的使用模式,而不是“理想的规范化形式”。这包括在多个位置复制某些数据(如果经常一起访问)。如果您有 RDBMS/SQL 经验,那么很容易立即选择 3NF/5NF 等。这是最常见的反模式。另一个则相反:将所有数据存储在一起,而不是如何访问它们。
官方文档
我会推荐官方文档,因为基于意见的答案就像这个一样😂可能会变得不一致:
200
推荐