您希望以反映您打算如何使用数据的方式来构建您的集合和文档。如果您要执行大量复杂查询,尤其是子文档,您可能会发现将文档拆分为单独的集合更容易。这方面的一个例子是从博客文章中拆分评论。
您的评论可以存储为子文档数组:
# Example post document with comment subdocuments
{
title: 'How to Mongo!'
content: 'So I want to talk about MongoDB.',
comments: [
{
author: 'Renold',
content: 'This post, it's amazing.'
},
...
]
}
但是,如果您只想对评论进行复杂查询(例如,从所有帖子中选择最新评论或获取一位作者的所有评论),这可能会导致问题。如果您打算进行这些复杂查询,那么您会更好关闭创建两个集合:一个用于评论,另一个用于帖子。
# Example post document with "ForeignKeys" to comment documents
{
_id: ObjectId("50c21579c5f2c80000000000"),
title: 'How to Mongo!',
content: 'So I want to talk about MongoDB.',
comments: [
ObjectId("50c21579c5f2c80000000001"),
ObjectId("50c21579c5f2c80000000002"),
...
]
}
# Example comment document with a "ForeignKey" to a post document
{
_id: ObjectId("50c21579c5f2c80000000001"),
post_id: ObjectId("50c21579c5f2c80000000000"),
title: 'Renold',
content: 'This post, it's amazing.'
}
这类似于您在关系数据库中存储“外键”的方式。像这样规范化您的文档可以轻松查询评论和帖子。此外,由于您正在拆分文档,因此每个文档将占用更少的内存。但是,权衡是,ObjectId
只要任一文档发生更改(例如,当您插入/更新/删除评论或帖子时),您都必须维护引用。而且由于 Mongo 中没有事件挂钩,因此您必须这样做您的应用程序中的所有这些维护。
另一方面,如果您不打算对文档的子文档进行任何复杂的查询,您可能会从存储单体对象中受益。例如,用户的偏好不是您可能会查询的内容:
# Example user document with address subdocument
{
ObjectId("50c21579c5f2c800000000421"),
name: 'Howard',
password: 'naughtysecret',
address: {
state: 'FL',
city: 'Gainesville',
zip: 32608
}
}