【发布时间】:2014-12-24 15:53:24
【问题描述】:
我刚开始使用 MongoDB,对于如何构建文档来解决以下问题有点迷茫(请注意,这只是一个与我遇到的困难相匹配的基本示例)。
问题:
假设我有一个名为Family 的顶级文档,这些文档存储在一个名为families 的集合中,并包含有关家庭的一些基本信息,即
{
_id: ObjectId("foobar"),
familyName: "Simpson",
address: "743 Evergreen Terrace, SpringField",
children: [
{
_id: ObjectId("barfoo"),
firstName: "Bartholomew",
preferredName: "Bart",
middleName: "JoJo"
}
// ... etc.
]
}
现在,假设我正在向我的应用程序添加另一个顶级文档:School,存储在名为 schools 的集合中。我需要将每个孩子与他们的学校联系起来,每个孩子在任何时候都只能上一所学校。我将如何在 Mongo 中解决这个问题?我来自一个非常沉重的 RDBMS 背景,我很难弄清楚这一点。我在解决方案中遇到的主要问题围绕着我需要有效处理以下用例:
- 查看一所学校并能够查看那里注册的所有儿童
- 查看一个家庭并查看其子女就读的所有学校
我尝试过的:
将子引用存储在 `School` 中
我采用的第一个解决方案是在我的School 文档中创建一个enrollments 数组,该数组引用了一个孩子的_id 以及他们的全名以方便起见,即
{
_id: ObjectId("asdadssa"),
name: "Springfield Elementary",
enrollments: [
{
child_id: ObjectId("barfoo"), // Bart Simpson
fullName: "Bart Simpson" // concatenation of preferredName and familyName
}
]
}
这对于第一个用例来说似乎很棒,它只需要显示在特定学校注册的所有学生。
但是,当我转向第二个用例时,我意识到我可能犯了一个错误。您到底如何确定Family 中的每个孩子属于哪所学校?我能看到的唯一方法是实际遍历schools 集合中的每一所学校,深入到他们的enrollments 并查看 child_id 是否与家庭中的孩子匹配......似乎不是很有效?这导致了我的下一次尝试。
在子对象中存储对学校的引用
因为每个孩子只能属于一所学校,我想我可以只在每个孩子的子文档中存储对 School 文档的引用,即 Bart 的文档现在将变为:
{
_id: ObjectId("barfoo"),
firstName: "Bartholomew",
preferredName: "Bart",
middleName: "JoJo",
school_id: ObjectId("asdadssa")
}
现在第二个用例很满意,但第一个不满意。
结论
我可以看到两个用例都得到满足的唯一方法是,如果我同时使用这两种解决方案,即将school_id 存储在子子文档中,并将child_id 存储在enrollments 数组中。
这对我来说似乎很笨拙,这意味着每次注册更改您至少需要执行两次写入(从学校移除并更改孩子)。据我所知,MongoDB 只有原子写入,没有事务支持,所以这看起来像是数据完整性可能受到影响的地方。
如果任何 MongoDB 专家可以提出替代解决方案,那就太好了。我知道这个特殊的问题真的叫“RDBMS !!!”,但这只是应用程序的一小部分,其他一些数据确实适合文档存储。
我现在只处于计划阶段,所以我不是 100% 致力于 Mongo,但我想我会试一试,因为我听到了一些关于它的好消息。
【问题讨论】:
标签: node.js mongodb database-design schema