六、数据模型引用
文档
我们已经知道MongoDB以文档的形式存储数据,而文档是JSON风格的数据结构,由一系列的“字段名-值”对组成,如下所示
{ "item": "pencil", "qty": 500, "type": "no.2" }
大多用户可访问的数据结构是文档,这些文档可以表示很多含义,包括:
- 所有数据库记录。
- 查询选择器,定义选择什么样的记录用以读取、更新和删除操作。
- 更新定义,定义需要修改哪些字段。
- 索引指定,定义对哪些字段加索引。
- 用于MongoDB报道以及配置的数据输出,例如serverStatus的输出和复制集配置文档。
文档格式
MongoDB在磁盘上以BSON的序列化格式存储文档。BSON就是JSON文档的二进制表现,尽管BSON包含了比JSON更多的数据类型。
mongo的JavaScript脚本与MongoDB语言驱动器用于在BSON和语言有关的文档表现形式之间转换。
文档结构
文档的形式如下
{
field1: value1,
field2: value2,
field3: value3,
...
fieldN: valueN
}
字段的值可以是任意的BSON数据类型,也包括其他文档、数组和文档数组。下面的示例文档包含了各种类型
var mydoc = {
_id: ObjectId("5099803df3f4948bd2f98391"),
name: { first: "Alan", last: "Turing" },
birth: new Date('Jun 23, 1912'),
death: new Date('Jun 07, 1954'),
contribs: [ "Turing machine", "Turing test", "Turingery" ],
views : NumberLong(1250000)
}
数据库引用
因为MongoDB的文档结构*灵活不固定,所以这使得MongoDB不支持连接操作。数据去规范化存储,或者存储有关的数据到文档中,可以免去对连接的需要,当然这有可能导致有关的信息被存储在不同的文档中,而且通常这些文档位于不同的集合甚至不同的数据库中。
MongoDB的应用程序如要将不同的文档联系起来,可以使用以下两种方法中的一种:
- 手动引用,在一个文档中存储另一个文档的_id字段。这样,应用程序可以使用一个二次查询来返回需要的数据。这些引用在大多数情况下都很简单并且足够用。
- DBRefs,一个文档中引用另一个文档,引用内容包括:被引用的文档的_id字段,集合名,甚至还可以有数据库名。通过包含这些名称,DBRefs可以用一个集合中的文档简单方便地与位于其他集合中的文档联系起来。为了解析DBRefs,程序也需要执行额外的查询才能得到被引用的文档。很多驱动都有一些帮助方法来自动为DBRef生成查询,不过驱动不会自动解析DBRefs生成文档(一些社区支持的驱动可以切换行为从而有可能可以自动解析DBRef为文档)。DBRefs提供一个通过的格式和类型来表征文档间的关系。如果数据库必须与多个框架和工具进行交互,那DBRefs格式也提供表征文档之间的联系的通用语义。
手动引用
考虑如下示例,使第一个文档的_id字段作为第二个文档的引用
original_id = ObjectId() db.places.insert({
"_id": original_id,
"name": "Broadway Center",
"url": "bc.example.net"
}) db.people.insert({
"name": "Erin",
"places_id": original_id,
"url": "bc.example.net/Erin"
})
这样,一个查询从people集合中返回后,就可以跟进返回结果中的places_id字段值对places集合做第二个查询。
手动引用是非常简单的,解析引用也是决定于程序是否需要。
DBRefs
DBRefs约定是表征一个文档,而非一个特定的引用类型。DBRefs除了包含_id字段值,还包含集合名,某些情况下还包括数据库名。
格式如下:
$ref:字段保持着被引用的文档所在集合的名称
$id:包含了被引用文档的_id字段值
$db:这是一个可选项。包含了被引用文档所在数据库的名称,注意仅部分驱动支持$db引用。
{ "$ref" : <value>, "$id" : <value>, "$db" : <value> }
示例,考虑一个文档,其在creator字段中存储了DBRef
{
"_id" : ObjectId("5126bbf64aed4daf9e2ab771"),
// .. application fields
"creator" : {
"$ref" : "creators",
"$id" : ObjectId("5126bc054aed4daf9e2ab772"),
"$db" : "users"
}
}
注意,通常来说,使用手动引用就可以了,如果需要引用多个集合中的文档,则考虑使用DBRefs。