Mongodb 做为一种 NoSql, 它的优点就是可以极好的与面向对象的语言相结合, 那面向对象的语言就会产生一些复杂的数据结构, 本节笔记就讲解如何将这些复杂对象映射到 Mongodb 里.
内嵌对象
所谓内嵌对象, 就是类似 Dict 那样, 把另一个对象做为 Dict 中某个字段的 value, 如:
{name: '张三', school: {name: '理工大学', city: '上海'}}
内嵌对象的__优点__就是__读取__非常快、方便, 可以一次性把相关的数据都读取出来.
再说说 内嵌对象 的__缺点__
就拿上面的 学生 => 学校 的例子来说, 如果存在几千几万个学生呢?
那 school: {name: ‘理工大学’, city: ‘上海’} 这种数据就存储了成千上万份, 不过这不是重点, 这种大数据量的存储还是没问题的, 但是..如果学校搬城市了呢? 从上海搬到南京了…那就要把所有的对象都更新次…这种更新的动作消耗就比较大了.
所以, 内嵌对象 的方式不适合这种 被内嵌的对象经常变动 的情况.
另外, 还有些复杂的对象是 内嵌对象 的方式无法表达的
例如存储 C 盘里所有目录/子目录的数据, 想一想, 如果用 内嵌对象 的方式, 每个目录都是对象, 它里面又包含了子对象, 子对象的里面还有子对象…这样下去无穷尽了…
再例如存储交友信息, 每个人都是对象, 如果用 内嵌对象, 那就会出现这种情况: A 里面有 B, B 里面又有 A…限入死循环了…
引用对象
为了解决 内嵌对象 方式的缺点, 引入了 引用对象 的方式.
这种方式的做法是, 在对象中只保存另一个对象的 _id 字段, 取数据的话先取出 _id, 然后根据 _id 再去取数据…
很明显这种方式的__缺点__就是取数据时要取__多次__(Mongodb 不支持 SQL 中的 Join, 即联合查询).
除了自己去实现这种引用关系外, Mongodb 也提供了自己的引用设计: DBRefs
语法如下:
{ $ref: $id: $db: }
参数说明:
- ref: 集合名称
- id: 引用的 id
- db: 可选, 数据库名称, 默认为当前所在库
如下面这个实例中用户数据文档中的 address 字段使用了 DBRef:
{ '_id':ObjectId('53402597d852426020000002'), 'name': 'Tom Benzamin' 'address': { '$ref': 'address_home', '$id': ObjectId('534009e4d852427820000002'), '$db': 'w3cschoolcc' }, }
address DBRef 字段指定了引用的数据地址是在 w3cschoolcc 数据库下的 address_home 集合中, 其 _id 为 534009e4d852427820000002.
通过下面这种方式, 可以取出 address 数据:
var user = db.users.findOne({'name':'Tom Benzamin'}) db[user.address.$ref].findOne({'_id':(dbRef.$id)})
根据官方推荐, 当这种引用关系是建立在同一个集合中时, 就用第一种自己保存 _id 的方式, 如果是夸集合引用, 请使用 DBRef.