MongoDB 中的關(guān)系表示文檔之間的邏輯相關(guān)方式。關(guān)系可以通過(guò)內(nèi)嵌(Embedded)或引用(Referenced)兩種方式建模。這樣的關(guān)系可能是 1:1、1:N、N:1,也有可能是 N:N。
先來(lái)考慮保存用戶地址的例子。一個(gè)用戶可能有多個(gè)地址,這是一個(gè) 1:N 的關(guān)系。
下面是一個(gè)結(jié)構(gòu)非常簡(jiǎn)單的 user 文檔。
{
"_id":ObjectId("52ffc33cd85242f436000001"),
"name": "Tom Hanks",
"contact": "987654321",
"dob": "01-01-1991"
}
下面是 address 文檔的結(jié)構(gòu):
{
"_id":ObjectId("52ffc4a5d85242602e000000"),
"building": "22 A, Indiana Apt",
"pincode": 123456,
"city": "Los Angeles",
"state": "California"
}
利用內(nèi)嵌方法,我們將把地址文檔內(nèi)嵌到 user 文檔中。
{
"_id":ObjectId("52ffc33cd85242f436000001"),
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin",
"address": [
{
"building": "22 A, Indiana Apt",
"pincode": 123456,
"city": "Los Angeles",
"state": "California"
},
{
"building": "170 A, Acropolis Apt",
"pincode": 456789,
"city": "Chicago",
"state": "Illinois"
}]
}
該方法會(huì)將所有相關(guān)數(shù)據(jù)都保存在一個(gè)文檔中,從而易于檢索和維護(hù)。通過(guò)一個(gè)查詢命令就能檢索整個(gè)文檔:
>db.users.findOne({"name":"Tom Benzamin"},{"address":1})
其中的 db 和 users 分別對(duì)應(yīng)的是數(shù)據(jù)庫(kù)和集合。
這種方法的缺點(diǎn)是,如果內(nèi)嵌文檔不斷增長(zhǎng),會(huì)對(duì)讀寫(xiě)性能造成影響。
這是一種設(shè)計(jì)歸一化關(guān)系的方法。按照這種方法,所有的用戶和地址文檔都將分別存放,而用戶文檔會(huì)包含一個(gè)字段,用來(lái)引用地址文檔 id 字段。
{
"_id":ObjectId("52ffc33cd85242f436000001"),
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin",
"address_ids": [
ObjectId("52ffc4a5d85242602e000000"),
ObjectId("52ffc4a5d85242602e000001")
]
}
如上所示,user 文檔包含的數(shù)組字段 address_ids 含有相應(yīng)地址的 ObjectId 對(duì)象。利用這些 ObjectId,能夠查詢地址文檔,從而獲取地址細(xì)節(jié)信息。利用這種方法時(shí),需要進(jìn)行兩種查詢:首先從 user 文檔處獲取 address_ids,其次從 address 集合中獲取這些地址。
>var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1})
>var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})