天天看点

mongodb——BSON类型

作者:老葛说码

BSON是一种二进制序列化格式,用于在MongoDB中存储文档和进行远程过程调用。BSON规范位于bsonspec.org上。

每种BSON类型都有整数和字符串标识符,如下表所示:

类型 编号 别名 注释
Double 1 "double"
String 2 "string"
Object 3 "object"
Array 4 "array"
Binary data 5 "binData"
Undefined 6 "undefined" Deprecated.
ObjectId 7 "objectId"
Boolean 8 "bool"
Date 9 "date"
Null 10 "null"
Regular Expression 11 "regex"
DBPointer 12 "dbPointer" Deprecated.
JavaScript 13 "javascript"
Symbol 14 "symbol" Deprecated.
JavaScript code with scope 15 "javascriptWithScope" Deprecated in MongoDB 4.4.
32-bit integer 16 "int"
Timestamp 17 "timestamp"
64-bit integer 18 "long"
Decimal128 19 "decimal"
Min key -1 "minKey"
Max key 127 "maxKey"
  • $type操作符支持使用这些值按其BSON类型查询字段。$type还支持数字别名,与整数、十进制、双精度和长整型BSON类型匹配。
  • $type聚合操作符返回其参数的BSON类型。
  • $isNumber聚合操作符在版本4.4中新增,如果其参数是BSON整数、十进制、双精度或长整型,则返回true。

要确定字段的类型,请参见mongo Shell中的“检查类型”。

如果要将BSON转换为JSON,请参阅“Extended JSON reference”。

以下各节介绍特定BSON类型的特殊注意事项。

ObjectId

ObjectId是小型、可能唯一、生成速度快且有序的。ObjectId值长度为12字节,由以下组成:

  1. 4字节时间戳值,表示ObjectId的创建时间,以自Unix纪元以来的秒数为单位。
  2. 每个进程一次性生成的5字节随机值。该随机值对于计算机和进程而言是唯一的。
  3. 3字节递增计数器,初始化为随机值。

虽然BSON格式本身是小端格式,但时间戳和计数器值是大端格式,在字节序列中最显著的字节先出现。

在MongoDB中,存储在集合中的每个文档都需要一个唯一的_id字段,作为主键。如果插入的文档省略了_id字段,则MongoDB驱动程序会自动为_id字段生成ObjectId。

这也适用于通过upsert:true进行插入的文档更新操作。

MongoDB客户端应添加带有唯一ObjectId的_id字段。使用ObjectId作为_id字段提供以下附加效益:

  • 在mongo shell中,可以使用ObjectId.getTimestamp()方法访问ObjectId的创建时间。
  • _ id字段存储ObjectId值时的排序与按创建时间排序大致相当。

虽然ObjectId值随时间增加,但它们不一定单调递增。这是因为它们:

仅包含1秒的时间分辨率,因此在同一秒内创建的ObjectId值没有保证的排序;

是由客户端生成的,这些客户端的系统时钟可能不同。

String

BSON字符串是UTF-8编码的。通常,每种编程语言的驱动程序在序列化和反序列化BSON时都将其从该语言的字符串格式转换为UTF-8。这使得大多数国际字符可以轻松地存储在BSON字符串中。 [1] 此外,MongoDB $regex查询支持在正则表达式字符串中使用UTF-8。

[1] 给定使用UTF-8字符集的字符串,在字符串上使用sort()会比较正确。然而,由于内部sort()使用C++ strcmp API,因此排序顺序可能会错误处理某些字符。

Timestamps

BSON具有用于MongoDB内部使用的特殊时间戳类型,并且与常规Date类型无关。此内部时间戳类型是64位值,其中:

  1. 最高32位是time_t值(自Unix纪元以来的秒数)。
  2. 最低32位是给定秒内操作的递增顺序。

虽然BSON格式是小端格式,因此先存储最低有效位,但mongod实例在所有平台上始终比较time_t值和序数值,而不管字节序如何。

在单个mongod实例中,时间戳值始终唯一。

在复制中,oplog具有一个ts字段。该字段中的值反映了操作时间,使用BSON时间戳值作为其时间戳。

BSON时间戳类型是供MongoDB内部使用的。在大多数情况下,应用程序开发中,您可能希望使用BSON日期类型。有关更多信息,请参见“Date”。

当插入包含空时间戳值的顶级字段的文档时,MongoDB将这些空时间戳值替换为当前时间戳值,除非_id字段本身包含一个空时间戳值,否则它将始终按原样插入而不被替换。

例:

插入一个空timestamp的文档

db.test.insertOne( { ts: new Timestamp() } );           

运行 db.test.find() 命令将返回一个类似以下文档的文档:

{ "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1) }           

服务器已经将ts字段的空时间戳值替换为插入时的时间戳值。

Date

BSON日期是一个64位整数,表示自Unix纪元(1970年1月1日)以来的毫秒数。这导致可表示的日期范围大约为290万年,包括过去和未来。

官方的BSON规范将BSON日期类型称为UTC日期时间。

BSON日期类型是有符号的。负值表示1970年之前的日期。

例:

在Mongo shell中使用new Date()构造函数构造一个日期:

var mydate1 = new Date()           

在Mongo shell中使用ISODate()构造函数构造一个日期:

var mydate2 = ISODate()           

将日期值作为字符串返回:

mydate1.toString()           

返回一个日期值的月份部分,其中月份是从0开始计数的,因此1月为0:

mydate1.getMonth()           

[2]在2.0版本之前,日期值被错误地解释为无符号整数,这影响了对日期字段的排序、范围查询和索引。由于在升级时不会重新创建索引,请重新创建索引(如果您在早期版本中使用日期值创建了索引)并且您的应用程序涉及1970年之前的日期。