MongoDB嵌套或拆分最佳实践

时间:2012-12-09 20:09:47

标签: mongodb mongodb-query

我想知道是否有人知道你是否可以过度使用嵌入MongoDB。没有说100级深度,在我的应用程序中我的平均文档大小可以变得非常大,简单的测试显示177kb的文档。

该应用程序用于日志记录,因此例如我使用Apache访问日志并从中获取大量内容,例如所有被调用页面的列表,点亮所有IP地址等等。这些都是分钟完成的。

我不太可能拥有一个符合MongoDB文档大小限制的文档,但想知道我是否将每个子列表保留为自己的文档,这样可以提高性能,返回子集信息(查询5分钟内发生的所有IP地址)。

当我运行查询时,我过滤只显示IP地址,如果我将每分钟分组到一个文档中,我是否在浪费数据库性能,或者如果我将每个列表拆分为自己的文档,我是否在浪费它?

1 个答案:

答案 0 :(得分:1)

您希望以反映您打算如何使用数据的方式构建您的集合和文档。如果您要执行大量复杂查询(尤其是子文档),您可能会发现将文档拆分为单独的集合更容易。这方面的一个例子是从博客帖子中分割评论。

您的评论可以存储为子文档数组:

# 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.'
}

这类似于在关系数据库中存储“ForeignKeys”的方式。像这样规范化您的文档可以轻松查询评论和帖子。此外,由于您正在分解文档,因此每个文档占用的内存都会减少。然而,权衡是,每当对任一文档进行更改时(例如,当您插入/更新/删除注释或发布时),您必须维护ObjectId引用。并且因为Mongo中没有事件挂钩,你必须在你的应用程序中进行所有这些维护。

另一方面,如果您不打算对文档的子文档执行任何复杂查询,则可能会从存储整体对象中受益。例如,用户的偏好不是您可能要查询的内容:

# Example user document with address subdocument
{
    ObjectId("50c21579c5f2c800000000421"),
    name: 'Howard',
    password: 'naughtysecret',
    address: {
        state: 'FL',
        city: 'Gainesville',
        zip: 32608
    }
}