BSON类型
BSON 是一种二进制序列化格式,用在 MongoDB 中存储文档和进行远程过程调用。BSON 规范位于 bsonspec.org。
每个 BSON 类型都同时具有整数和字符串标识符,如下表所列:
类型 | 数值 | 别名 | 注意 |
---|---|---|---|
double | 1 | "double" | |
字符串 | 2 | "string" | |
对象 | 3 | "object" | |
阵列 | 4 | "array" | |
二进制数据 | 5 | "binData" | |
未定义 | 6 | "undefined" | 已弃用。 |
ObjectId | 7 | "objectId" | |
布尔 | 8 | "bool" | |
Date | 9 | "date" | |
null | 10 | "null" | |
正则表达式 | 11 | "regex" | |
数据库指针 | 12 | "dbPointer" | 已弃用。 |
JavaScript | 13 | "javascript" | |
符号 | 14 | "symbol" | 已弃用。 |
32 位整数 | 16 | "int" | |
时间戳 | 17 | "timestamp" | |
64 位整型 | 18 | "long" | |
Decimal128 | 19 | "decimal" | |
Min key | -1 | "minKey" | |
Max key | 127 | "maxKey" |
$type
操作符支持使用这些值按 BSON 类型查询字段。$type
还支持number
别名,它匹配整数、十进制、double 和长整型 BSON 类型。$type
聚合操作符返回其参数的 BSON 类型。如果参数是 BSON 整数、小数、double 或长整数,则
$isNumber
聚合操作符会返回true
。4.4 版新增功能
要确定某一字段的类型,请参阅类型检查。
如果将 BSON 转换为 JSON,请参阅扩展 JSON 参考资料。
以下部分介绍了特定 BSON 类型的特别注意事项。
二进制数据
BSON 二进制binData
值是字节数组。binData
值有一个子类型,表示如何解释二进制数据。下表显示了子类型。
数值 | 子类型 |
---|---|
0 | 通用二进制子类型 |
1 | 函数数据 |
2 | 二进制(旧版) |
3 | UUID(旧) |
4 | UUID |
5 | MD5 |
6 | 加密的 BSON 值 |
7 | 压缩时间序列数据 5.2 版本中的新增功能。 |
128 | 自定义数据 |
ObjectId
ObjectId(对象标识符)很小,可能是唯一的,生成速度快并且是有序的。ObjectId 值的长度为 12 个字节,包含:
一个 4 字节时间戳,它表示 ObjectId 的创建时间,并以自 UNIX 纪元以来的秒数为单位进行测量。
每个进程会生成一次 5 字节随机值。这个随机值对于机器和进程是唯一的。
三字节递增计数器(初始化为随机值)。
对于时间戳和计数器值,最高有效字节在字节序列中最先出现(大端字节序)。对于其他 BSON 值,最低有效字节最先出现(小端字节序)。
如果使用整数值创建对象标识符(ObjectId),则该整数将替换时间戳。
在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略了 _id
字段,则 MongoDB 驱动程序会自动为 _id
字段生成一个 ObjectId。
这也适用于通过执行 upsert: true 的更新操作插入的文档。
MongoDB 客户端应添加一个具有唯一 ObjectId 的 _id
字段。为 _id
字段使用 ObjectId 还能带来以下好处:
您可以使用
ObjectId.getTimestamp()
方法访问mongosh
中的ObjectId
创建时间。ObjectID 大致按创建时间排序,但并非完全有序。在包含
ObjectId
值的_id
字段上对集合排序,大致相当于按创建时间排序。
使用 ObjectId()
方法可设置和检索 ObjectId 值。
从 MongoDB 5.0 开始,mongosh
将取代旧版的 mongo
shell。ObjectId()
方法在 mongosh
中的运行方式与在旧版的 mongo
shell 中的运行方式不同。有关旧版方法的更多信息,请参阅旧版的 mongo Shell。
字符串
BSON 字符串是 UTF-8 编码。通常,在序列化和反序列化 BSON 时,每种编程语言的驱动程序会从该语言的字符串格式转换为 UTF-8。这样就可以在 BSON 字符串中轻松存储大多数国际字符。[1]此外,MongoDB$regex
查询支持在正则表达式字符串中使用 UTF-8。
[1] | 对于使用 UTF-8 字符集的字符串,使用 sort() 排序通常可以得到正确的结果。但是,由于 sort() 内部使用 C++ strcmp api,因此某些字符的排序处理可能不正确。 |
时间戳
BSON 具一种特殊的时间戳类型,供 MongoDB 内部使用,与常规的 Date 类型无关。此内部时间戳类型是 64 位值,其中:
最高的 32 位有效位则是
time_t
值(自 UNIX 纪元以来的秒数)对于给定秒内的操作,最低有效的 32 位是递增的
ordinal
。
虽然 BSON 格式是小端字节序,因此首先存储最低有效位,但在所有平台上,mongod
实例始终先比较 time_t
值,然后再比较 ordinal
值,不受字节序的影响。
在单个 mongod
实例中,时间戳值总是唯一的。
在复制中,oplog 有一个 ts
字段。该字段的值反映利用 BSON 时间戳值确定的操作时间。
注意
这种 BSON 时间戳类型供 MongoDB 内部使用。对于多数情况,应用程序开发中需要使用 BSON 日期类型。请参阅日期,获取更多信息。
当插入的文档包含具有空时间戳值的顶级字段时,MongoDB 会将空时间戳值替换为当前时间戳值,但以下情况除外。_id
字段如果本身包含空时间戳值,则将始终按原样插入而不被替换。
例子
插入附带空时间戳值的文档:
db.test.insertOne( { ts: new Timestamp() } );
随后运行 db.test.find()
将返回一个类似如下内容的文档:
{ "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1) }
服务器已将 ts
的空时间戳值替换为插入时的时间戳值。
Date
“BSON Date”(BSON 日期)是一个 64 位整数,它表示自 UNIX 纪元(1970 年 1 月 1 日)以来的毫秒数。因此,过去与未来的可表示日期范围便可达到约 2.9 亿年。
官方 BSON 规范将 BSON 日期类型称为 UTC 日期时间。
BSON Date 类型为有符号值。[2] 负值代表 1970 年之前的日期。
例子
使用 mongosh
中的 new Date()
构造函数来构造日期:
var mydate1 = new Date()
例子
使用 mongosh
中的 ISODate()
构造函数来构造日期:
var mydate2 = ISODate()
例子
以字符串形式返回该日期值:
mydate1.toString()
例子
返回 Date 值的月份部分;月份从零开始索引,因此一月是月份 0
:
mydate1.getMonth()
[2] | 在 2.0 版本之前,Date 值被错误解释为无符号整数,从而会影响针对 Date 字段的排序、范围查询和索引。由于升级时不会重新创建索引,因此使用早期版本对 Date 值创建索引时请重新创建索引,且 1970 年之前的日期对您的应用程序来说均为相对日期。 |