本章介绍以下MongoDB中的document相关概念。

MongoDB将数据记录作为BSON documents来进行存储。BSON是JSON documents的一种二进制表示方式,但是其具有比JSON更多的数据类型(data types)。参看bsonspec.orgBSON Types.

mongodb-bson

1. Document Structure

MongoDB文档是由field-value对所组成,并且有如下结构:

{
   field1: value1,
   field2: value2,
   field3: value3,
   ...
   fieldN: valueN
}

其中value字段可以是任何的BSON data types,包括其他的documents、arrays以及arrays of documents。例如,下面的document包含多种类型的values:

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维持着一个内嵌的document,该document含有first及last两个字段;

  • birthdeath维持着日期类型的值

  • contribs维持着字符串数组

  • views维持着一个NumberLong类型的值

1) FieldNames

字段的名称是字符串类型。

documents的字段名称具有如下限制:

  • 字段名称_id保留,用作主键(primary key)。其值在整个集合中唯一,并且是不可修改的,可以是除数组之外的任何类型。假如_id包含子字段(subfields)的话,则子字段的名称不能以$符号开头

  • 字段的名称不能包含null字符

  • 服务器允许存储的字段名称包含.(dot)和美元符号($)

  • MongoDB 5.0对字段名称中的$.符号提供了更高级的支持。同时也有一些限制,请参看Field Name Considerations以了解更多细节。

BSON文档可以有多个字段含有相同的名称。然而大部分MongoDB接口的内部数据结构实现都不支持有相同的字段名称。假如你需要操作含有相同字段名称的documents,请参看driver documentation

有一些由MongoDB内部进程所创建的documents可能含有相同名称的字段,但是并没有相关的方法可以向用户documents中添加重复的字段。

2) Field Value Limit

从MongoDB 2.6到featureCompatibilityVersion (fCV)被设置为4.0的版本:针对indexed collections,索引字段的值的长度有Maximum Index Key Length限制。请参看Maximum Index Key Length以了解更多细节。

1.1 Dot Notation

MongoDB使用.符号来访问数组元素和内嵌的document字段。

1) Arrays

可以通过.符号来设置或访问下标从0开始的数组元素。具体方式为:

"<array>.<index>"

其中<array>为数组名,<index>为从0开始的下标。另外注意外层的引号

下面的例子中,含有一个字段为contribs的document:

{
   ...
   contribs: [ "Turing machine", "Turing test", "Turingery" ],
   ...
}

如果要指定contribs数组的第三个元素,请使用"contribs.2"

对于查询数组,请参看:

See Also:

$[]针对更新操作的所有位置操作符

[$[]](https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#mongodb-update-up.---identifier--)针对更新操作的过滤的位置操作符

$针对更新操作的位置操作符

$当数组索引位置不确定时的projection操作符

Query An Array点符号访问数组示例

2) Embedded Documents

可以使用.符号来设置或访问内嵌document的字段。具体方式如下:

"<embedded document>.<field>"

注: 外层含有引号

例如,给定含有下面字段的document:

{
   ...
   name: { first: "Alan", last: "Turing" },
   contact: { phone: { type: "cell", number: "111-222-3333" } },
   ...
}
  • 要设置name字段的last分量的值时,可以使用"name.last"

  • 要设置contact字段的电话号码时,可以使用"contact.phone.number"

更多查询内嵌document的示例,请参看:

1.2 Document Limitations

Documents有如下的一些属性:

1) Document Size Limit

BSON document的最大大小为16M字节。最大大小的限制确保了单个document不会占用太多的内存,在进行传输时也不会消耗太多的带宽。要存储超过最大大小的documents,MongoDB提供了GridFs API。参看mongofiles,以及关于GridFs驱动的相关文档

2) Document Field Order

与JavaScript对象不同,BSON中的字段是有顺序的。

2.1) Field Order in Queries

对于查询,字段的顺序行为如下:

  • 当进行documents比较时,field的顺序也是有意义的。例如,当比较含有ab两个字段的document时:

    • {a: 1, b: 1}等于{a: 1, b: 1}
    • {a: 1, b: 1}不等于{b: 1, a: 1}
  • 在执行高效的查询时,查询引擎可能会在进行查询处理时对字段进行排序。其他场景下,在执行$project$addFields$set$unset这些projection操作符时也可能会对字段进行排序

    • 查询返回的中间结果或最后结果都有可能对字段进行排序
    • 由于有些操作可能对字段进行排序,因此在你使用上面列出的projection操作符时,不应该依赖于查询结果中字段的顺序

2.2) Field Order in Write Operations

对于写操作,MongoDB会保留document字段的顺序,除非遇到如下场景:

  • _id字段总是作为document的第一个字段

  • 包含对字段重命名(rename)的更新操作可能会更改document字段的顺序

2.3) The _id Field

在MongoDB中,存放在collection中的每一个document都有一个唯一的_id字段作为该document的主键(primary key)。假如一个插入的document省略了_id字段,则MongoDB会自动的为_id字段产生一个ObjectId

这同样适用于insert:true的update操作。

_id字段具有如下行为和限制:

  • 默认情况下,MongoDB会在创建collection时为_id字段创建一个唯一索引

  • _id字段总是作为documents的一个字段。假如服务器收到了一个document,其_id字段不是第一个字段,那么服务器会自动的将该字段移动为第一个字段

  • 假如_id字段的值包含子字段,则字段的fieldName不能以$符号开头。

  • _id字段的值可以是任何BSON data type,但是不能为array、regex、或undefined

警告:为了确保功复制功能运行正常,不要在_id字段存放BSON正则表达式

如下是存储_id字段的值时的一些常用选项:

  • 使用一个ObjectId

  • 假如可行的话,使用一个自然的唯一标识符。这可以节省存储空间,并且可以避免额外的索引。

  • 产生一个自增(auto-incrementing)数字

  • 通过应用程序代码产生一个UUID。为了更高效的在collection以及_id索引中存储UUID的值,将UUID作为一个BSON BinData类型。

采用BinData类型作为索引的key在如下的条件下可以获得更高的效率:

  • 二进制子类型的值在0~7或128~135范围内
  • 字节数组的长度为:0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 或32.

  • 使用驱动(driver)所提供的UUID设备来产生UUIDs。需要知道的是,driver所提供的UUID序列化与反序列化可能有不同的实现逻辑,因此可能与其他的driver不完全兼容。参看driver documentation以了解更多UUID互操作性信息。

Note:

大多数MongoDB驱动客户端都会包含_id字段,并在执行插入操作之前产生一个ObjectId。然而,假如客户端发送一个不带_id字段的document,那么MongoDB将会增加一个_id字段,并为其生成一个ObjectId

1.3 Other Uses of the Document Structure

除了用于定义数据记录(data record),MongoDB还全面使用document structure,包括且不限于:query filters, update specifications documents, index specification documents

1) Query Filter Documents

通过指定过滤条件来查询特定的documents以进行读取(read)、update、delete操作。

我们可以使用<field>:<value>表达式来指定相等条件(equality condition)以及query operator表达式。

{
  <field1>: <value1>,
  <field2>: { <operator>: <value> },
  ...
}

其他示例,请参看:

2) Update Specification Documents

使用update operators来更新特定的documents的指定字段。

{
  <operator1>: { <field1>: <value1>, ... },
  <operator2>: { <field2>: <value2>, ... },
  ...
}

更多示例,请参看Update specifications

3) Index Specification Documents

Index specification documents用于定义索引的字段(field)以及索引类型:

{ <field1>: <type1>, <field2>: <type2>, ...  }

1.4 Further Reading

关于MongoDB文档模型(document model)的更多信息,请下载 MongoDB Application Modernization Guide

可以从中下载到如下资源:

  • MongoDB数据模型的方法论介绍

  • 从RDBMS数据模型迁移到MongoD的最佳实践及考量白皮书(white paper)

  • 与RDBMS所对应的MongoDB schema参考

  • Application Modernization scorecard



[参看]:

  1. mongodb官网

  2. mongodb method

  3. mongodb command

  4. MongoDB Projection

  5. mongodb菜鸟教程

  6. 了解 MongoDB 看这一篇就够了