数据库引用的意义:
mongodb中数据的扫描是按行来扫描的,这意味着如果有一个字段的值长度很长,
mongodb不会自动跳过而是将整个文档扫描一遍,当数据量十分密集而这个很长的字段不需要经常被检索时会严重拖慢效率,
因此此时可以将其作为引用保存在其他的集合中
数据库关系
在传统的SQL数据库中,关系被分为一个个表(table),在表中,每个数据项以主键(primary key)标识,
而一个表的主键又作为另一个表的外键(reference key),在两个表之间引用。
当遇上多对多关系的时候,
还需要一个额外的关联表(reference table),将多对多关系转化成两个一对多关系。
而在MongoDB中,表示关系有两种办法:
一种是嵌套(embedded),既是将一个文档包裹一个子文档;
而另一种是引用链接(reference link),使用MongoDB的DBRef对象建立文档和文档之间的关系。
除此之外,MongoDB的关系可以有 1对1 , 1对N , N对1 和 N对N 几种关系。
嵌套
每个MongoDB文档都由BSON文档组成,有类似JSON格式一样的数据类型,
其中String、Int、Float称为基本类型(或常量),
而Hash和Array称之为复合类型。
所谓的嵌套,就是说文档中,利用复合类型,包裹一个多或多个其他类型的值,这些值称之为子文档。
文档嵌套的数量和深度没有限制,但MongoDB目前版本限制一个文档最大为16MB。
引用链接
比起嵌套,引用链接更接近传统意义上的(也就是,关系型数据库术语中的)“引用”,它是两个文档之间的一种关系。
引用链接通过DBRef对象建立,DBRef对象储存了如何找到目标文档的信息,
就像现实世界中的门牌号码一样(也类似关系型数据库中的外键)。
如果在一个文档A中,有一个DBRef对象,而这个DBRef对象储存了关于如何找到文档B的信息,
那么文档A就可以通过解释这个DBRef对象(称之为解引用)来获取文档B的数据。
什么时候使用DBRef
在MongoDB中表示这种对其他文档的引用关系,并不是只有DBRef方式.
两个集合 users(用户),notes(笔记),
用户可以创建笔记,笔记可以引用用户或者别的笔记.
db.users.insert({"_id":"refactor","displayName":"dis_refactor"})
db.users.insert({"_id":"refactor2","displayName":"dis_refactor2"})
db.notes.insert({"_id":2,"author":"refactor","text":"refactor in mongodb"})
db.notes.insert(
{
"_id":22,
"author":"refactor22",
"text":"...DBRef likes url",
"references":
[
{"$ref":"users","$id":"refactor"},
{"$ref":"notes","$id":2}
]
}
)
var note=db.notes.findOne({"_id":22});
note.references.forEach(
function(ref){
printjson(db[ref.$ref].findOne({"_id":ref.$id}));
});
上面的例子就用了另外一种引用:每个note的author键仅存储了author文档的"_id"键,没有必要用DBRef,
因为已经
知道每个author就是users集合里面的一个文档.- 这种引用在GridFS的块文档中"files_id"键仅仅就是对文档"_id"的引用.
在保存引用的时候是选择DBRef还是至存储"_id"?
保存"_id"会更加紧凑,对开发者而言就很轻量.
但是DBRef能够引用任意集合(甚至是任意数据库)的文档,开发者
不必知道和记住被引用的文档在哪些集合里面.- 驱动程序和一些工具对DBRef提供了额外的功能(如自动去引用).
总之,存储一些对 不同 集合的 文档的引用时,最好用DBRef.否则最好存储"_id"作为引用来使用,这样更简单,也更容易操作.
引用分类:
MongoDB使用引用来规范数据结构文档。
http://blog.csdn.net/fly910905/article/details/78279851
MongoDB 引用有两种:
手动引用(Manual References)
DBRefs
DBRefs vs 手动引用
考虑这样的一个场景,我们在不同的集合中 (address_home, address_office, address_mailing, 等)
存储不同的地址(住址,办公室地址,邮件地址等)。
这样,我们在调用不同地址时,也需要指定集合,一个文档从多个集合引用文档,我们应该使用 DBRefs。
使用 DBRefs
DBRef的形式:
{ $ref : , $id : , $db : }
三个字段表示的意义为:
$ref:集合名称
$id:引用的id
$db:数据库名称,可选参数
以下实例中用户数据文档使用了 DBRef, 字段 address:
{
"_id":ObjectId("53402597d852426020000002"),
"address": {
"$ref": "address_home",
"$id": ObjectId("534009e4d852427820000002"),
"$db": "w3cschoolcc"},
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin"
}
address DBRef 字段指定了引用的地址文档是在 address_home 集合下的 w3cschoolcc 数据库,id 为 534009e4d852427820000002。
以下代码中,我们通过指定 $ref 参数(address_home 集合)来查找集合中指定id的用户地址信息:
>var user = db.users.findOne({"name":"Tom Benzamin"})
>var dbRef = user.address
>db[dbRef.$ref].findOne({"_id":(dbRef.$id)})
以上实例返回了 address_home 集合中的地址数据:
{
"_id" : ObjectId("534009e4d852427820000002"),
"building" : "22 A, Indiana Apt",
"pincode" : 123456,
"city" : "Los Angeles",
"state" : "California"
}
DBRef的形式:
{ $ref : , $id : , $db : }
三个字段表示的意义为:
$ref:集合名称
$id:引用的id
$db:数据库名称,可选参数
以下实例中用户数据文档使用了 DBRef, 字段 address:
{
"_id":ObjectId("53402597d852426020000002"),
"address": {
"$ref": "address_home",
"$id": ObjectId("534009e4d852427820000002"),
"$db": "w3cschoolcc"},
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin"
}
address DBRef 字段指定了引用的地址文档是在 address_home 集合下的 w3cschoolcc 数据库,id 为 534009e4d852427820000002。
以下代码中,我们通过指定 $ref 参数(address_home 集合)来查找集合中指定id的用户地址信息:
>var user = db.users.findOne({"name":"Tom Benzamin"})
>var dbRef = user.address
>db[dbRef.$ref].findOne({"_id":(dbRef.$id)})
以上实例返回了 address_home 集合中的地址数据:
{
"_id" : ObjectId("534009e4d852427820000002"),
"building" : "22 A, Indiana Apt",
"pincode" : 123456,
"city" : "Los Angeles",
"state" : "California"
}
参考来源: http://www.runoob.com/mongodb/mongodb-database-references.html