本章内容
- 文档结构
- 点表示法
- 文档限制
- 文档结构的其他用途
- 延伸阅读
MongoDB将数据记录存储为BSON文档。 BSON是JSON文档的二进制表示形式,尽管它比JSON包含更多的数据类型。有关BSON规范,请参见bsonspec.org。另请参阅BSON类型。

一、文档结构
MongoDB文档由字段(field)和值(value)对组成,并且结构如下:
{
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)
}
上面的字段具有以下数据类型:
- _id持有一个ObjectId。
- name持有一个嵌入式文档,该文档包含first和last字段。
- birth和death持有Date类型的值。
- contribs持有一个字符串数组。
- views持有NumberLong类型的值。
1.字段名
字段名必须是字符串。
文档对字段名的限制如下:
- ”_id”是保留字段名,用作主键;它的值在集合中必须是唯一的,不可变的,并且可以是数组以外的任何类型。
- 字段名不能包含null字符。
- 顶级字段名不能以美元符号($)开头。 非顶级字段,从MongoDB 3.6开始,允许存储包含点(.)和美元符号($)的字段名称。
重要
MongoDB查询语言不能总是有效地表达对字段名称包含这些字符的文档的查询(请参阅SERVER-30575)。
在使用查询语言添加支持之前,请使用$和。不建议在字段名中使用“ in”,并且官方MongoDB驱动程序不支持。
BSON文档可能有多个具有相同名称的字段。但是,大多数MongoDB接口代表的MongoDB具有不支持重复字段名称的结构(例如哈希表)。如果需要处理具有多个同名字段的文档,请参见驱动程序的驱动程序文档。
内部MongoDB流程创建的某些文档可能具有重复的字段,但是没有MongoDB流程会向现有的用户文档添加重复的字段。
2.字段值的限制
MongoDB 2.6通过MongoDB版本控制将featureCompatibilityVersion(fCV)设置为“ 4.0”或更早版本
对于索引集合,索引字段的值具有“最大索引键长度”。有关详细信息,请参见最大索引密钥长度。
二、点表示法
MongoDB使用点表示法来访问数组的元素和访问嵌入式文档的字段。
1.数组
使用从零开始的索引位置指定或访问数组的元素,请使用点(.)将数组名称和索引(索引从零开始)连接起来,并用引号引起来:
"<array>.<index>"
例如,给定的文档中如下字段:
{
...
contribs: [ "Turing machine", "Turing test", "Turingery" ],
...
}
要指定contribs数组中的第三个元素,使用点符号“contribs.2”。
有关查询数组的示例,请参见:
也可以看看:
- $ []用于更新操作的所有位置运算符,
- $ [/ <identifier />]过滤后的位置运算符,用于更新操作,
- $用于更新操作的位置运算符,
- 数组索引位置未知时的$投影运算符
- 在数组中查询数组的点符号示例。
2.嵌入式文档
使用点符号指定或访问嵌入式文档的字段,使用点(.)将嵌入式文档名称与字段名连接在一起,并用引号引起来:
"<embedded document>.<field>"
例如,给定的文档含有以下字段:
{
...
name: { first: "Alan", last: "Turing" },
contact: { phone: { type: "cell", number: "111-222-3333" } },
...
}
- 指定name字段中的last字段,使用点符号“name.last”。
- 指定contact字段中phone文档中的number,使用点号“contact.phone.number”。
有关查询嵌入式文档的示例,请参见:
三、文档限制
文档具有以下属性:
1.文档大小限制
BSON文档大小限制最大为16 MB。
最大文档大小有利于确保单个文档不会使用过多的RAM或在传输过程中占用过多的带宽。
要存储大于最大大小的文档,MongoDB提供了GridFS API。有关GridFS的更多信息,请参阅mongofiles和驱动文档。
2.文档字段的排序
除以下情况外,MongoDB会在执行写操作后保留文档字段的顺序:
- _id字段始终是文档中的第一个字段。
- 包括重命名字段的更新可能导致文档中字段的重新排序。
3._id字段
在MongoDB中,集合中的每个文档都必须有一个唯一的_id字段作为主键。如果插入的文档缺省_id字段,则MongoDB驱动程序会自动为_id字段生成一个ObjectId类型值。
上述也适用于通过upsert:true更新文档。
_id字段具有以下特征和约束:
- 默认情况下,MongoDB在集合创建期间在_id字段上创建唯一索引。
- _id字段始终是文档中的第一个字段。如果服务器接收到文档的_id字段没在第一个位置,则服务器会将字段移到开头。
- _id字段可以包含任何BSON数据类型的值,数组除外。
警告
为确保复制正常进行,请勿在_id字段中存储BSON正则表达式类型的值。
存储_id值的常用选项如下:
- 使用ObjectId类型。
- 使用自然唯一标识符,这样可以节省空间并避免附加索引。
- 生成一个自动递增的数字。
- 在应用程序代码中生成一个UUID。
为了更有效地在集合和_id索引中存储UUID值,将UUID存储为BSON BinData类型的值。
如果满足以下条件,则可以更有效地将BinData类型的索引键存储在索引中:
1.二进制子类型的值在0-7或128-135的范围内,并且
2.字节数组的长度为:0、1、2、3、4、5、6、7、8、10、12、14、16、20、24或32。
- 使用驱动程序的BSON UUID工具生成UUID。请注意,驱动程序实现可能会以不同的方式实现UUID序列化和反序列化逻辑,这可能与其他驱动程序不完全兼容。请参阅驱动程序文档,以获取有关UUID互操作的信息。
注意
大多数MongoDB驱动程序客户端将包括_id字段,并在将插入操作发送到MongoDB之前生成一个ObjectId;但是,如果客户端发送的文档中没有_id字段,则mongod将添加_id字段并生成ObjectId。
四、文档结构的其他用途
除了定义数据记录,MongoDB还在整个文档结构中使用,包括但不限于:查询过滤器,更新规范文档和索引规范文档。
1.查询过滤文档
查询过滤文档:过滤出进行读取,更新和删除操作的数据记录。
可以使用<field>:<value>表达式指定:相等条件和查询运算符表达式。
{
<field1>:<value1>,
<field2>:{<operator>:<value>},
...
}
有关示例,请参见:
2.更新指定的文档
更新指定文档:使用更新运算符来确定要在db.collection.update()操作期间对指定字段执行的数据修改。
{
<operator1>:{<field1>:<value1>,...},
<operator2>:{<field2>:<value2>,...},
...
}
有关示例,请参阅更新指定文档。
3.索引指定的文档
索引指定文档定义了要索引的字段和索引类型:
{<field1>:<type1>,<field2>:<type2>,...}
五、延伸阅读
有关MongoDB文档模型的更多信息,请下载《 MongoDB应用程序现代化指南》。
下载内容包括以下资源:
- 演示使用MongoDB进行数据建模的方法
- 白皮书涵盖了从RDBMS数据模型迁移到MongoDB的最佳实践和注意事项
- 参考MongoDB模式及同等的RDBMS
- 应用程序现代化记分卡。