在MongoDB中设计数据库模式的正确方法

时间:2014-10-30 05:59:16

标签: c# mongodb schema

在我的应用程序中会有程序列表,每个程序将包含会话列表,每个会话将包含工作表列表。以更简单的方式,关系如下:

Programs --> Sessions --> Worksheets

在应用程序的某个时刻,我想以表格形式显示所选prgram的工作表列表:

--------------------------------
|Worksheet Name | Session Name |
--------------------------------
|Worksheet 1    | Session 2    |
|---------------|--------------|
|Worksheet 3    | Session 1    |
|---------------|--------------|
|               |              |

我的问题是我是否应该使用嵌入式文档,即在会话中嵌入prgram和worsheets中的会话,还是应该为程序,会话和工作表单独收集并使用类似于RDBMS中的外键的概念来关联它们?

我担心的是,如果我选择单独收集,那么对于上述情况,我将不得不执行太多查询以获得上述结果。

如果我去查询嵌套文档,那么查询子文档是非常有限的。

mongo中的文档限制为16MB,如果我使用嵌套文档,这就足够了。所以文档大小不是我关心的问题。

由于mongo基本上不是用于通货紧缩和规范化,所以我的问题是我是否应该使用关系来实现规范化模式,还是应该考虑上面的场景,使用嵌入式文档来获取规范化数据。

1 个答案:

答案 0 :(得分:0)

在MongoDB中,数据建模的指导原则是设计文档,以便轻松快速地完成应用程序的最常见查询。这与RDBMS中的模式设计非常不同,后者侧重于规范化数据以使其不同部分之间的关​​系形式化,然后依靠连接以通过关系中的非规范化来获得正确的信息。 MongoDB并不适用于关系"这是不正确的。确实,它不处理规范化数据以及RDBMS,因为它不执行连接。联接必须在应用程序端完成。

Pontification完成后,一种简单的数据建模方法,可以让您的查询变得简单,就是将工作表存储为文档,将会话和程序数据非规范化到每个工作表中

{
    "_id" : "p3s1ws0",
    "session_id" : "s1",
    "program_id" : "p3",
    ....
}

然后使用查询

检索给定program_id prog_id的所有工作表
> db.worksheets.find({ "program_id" : prog_id })

最有可能添加一种排序来生成所需的表格形式。另一个现实的选择是让会话文档包含一系列工作表文档,假设每个会话的工作表数量可以限制在合理的数量,比如说200:

{
    "_id" : "s0",
    "program_id" : "p2",
    "worksheets" : [
        {
            "_id" : "ws0",
            ...
        },
        ...
    ],
    ...
}

查询保持不变

db.sessions.find({ "program_id" : prog_id" })

因为您可以从每个会话中获取会话的所有工作表。根据您希望如何制作表格形式,可能值得为查询使用聚合,但在问题中没有必要使用聚合。

两者之间的选择取决于它将如何影响您的其他查询和更新。例如,更新程序信息对于第一个模型来说更昂贵,因为它需要针对程序中的每个工作表进行更新,而不是更新程序中的每个会话,或者如果数据被建模则只更新一个文档。作为包含工作表数组的会话数组的程序文档(可能不想这样做)。

要了解有关此类数据建模的更多信息,我建议来自MongoDB博客的William Zola classic series