数据类型
本页内容
MongoDB 使用BSON,它支持在JSON中不可用的附加数据类型。mongosh 壳在数据类型支持方面比传统的 mongo 壳要更好。
本文强调了 mongosh 和传统 mongo 壳之间类型使用的变更。有关受支持类型的更多信息,请参阅扩展 JSON 参考。
日期
mongosh 提供了各种方法来返回日期,可以是字符串或 Date 对象。
Date()方法,它返回当前日期作为字符串。new Date()构造函数,它使用ISODate()包装器返回一个Date对象。ISODate()构造函数,它使用ISODate()包装器返回一个Date对象。
ObjectId
mongosh 提供了围绕 ObjectId 数据类型的 ObjectId() 包装类。要生成新的 ObjectId,请在 mongosh 中使用以下操作
new ObjectId
从 1.8.0 版本开始,ObjectId 包装器不再接受
ObjectId.prototype.generate
ObjectId.prototype.getInc
ObjectId.prototype.get_inc
ObjectId.getInc
双精度浮点数
可以使用 Double() 构造函数显式指定双精度浮点数
db.types.insertOne( { "_id": 2, "value": Double(1), "expectedType": "Double" } )
注意
如果字段的值可以转换为32位整数,mongosh 将将其存储为 Int32。如果不能,mongosh 默认将其作为 Double 存储。要指定值类型,请使用 Double() 或 Int32() 构造函数。
Int32
Int32() 构造函数可以用于显式指定32位整数。
db.types.insertOne( { "_id": 1, "value": Int32(1), "expectedType": "Int32" } )
警告
如果你同时使用 mongosh 和旧版 mongo shell 连接到相同的集合,默认的 Int32 和 Double 类型可能会被不一致地存储。
长
LongLong() 构造函数可以用于显式指定64位整数。
db.types.insertOne( { "_id": 3, "value": Long(1), "expectedType": "Long" } )
十进制128位
Decimal128() 的值是128位的基于十进制的小数浮点数,可以精确地模拟十进制舍入。
此功能适用于处理货币数据的应用,例如金融、税务和科学计算。
Decimal128 BSON类型使用IEEE 754 decimal128浮点数格式,支持34位小数(即有效数字)和指数范围从-6143到+6144。
db.types.insertOne( { "_id": 5, "value": Decimal128("1"), "expectedType": "Decimal128" } )
注意
要使用带有MongoDB驱动程序的Decimal128数据类型,请确保使用支持它的驱动程序版本。
等价性和排序顺序
Decimal128类型的值与其他数值类型根据其实际数值进行比较和排序。基于二进制的Double类型的数值通常有基于十进制的值的近似表示,可能不等于它们的十进制表示。
时间戳
MongoDB在oplog中使用BSON时间戳。与Java时间戳类型类似,Timestamp类型。对于涉及日期的操作,请使用日期类型。
Timestamp签名有两个可选参数。
Timestamp( { "t": <integer>, "i": <integer> } )
参数 | 类型 | 默认值 | 定义 |
|---|---|---|---|
t | 整数 | 自 UNIX纪元 以来当前时间。 | 可选。以秒为单位的时间。 |
i | 整数 | 1 | 可选。当给定秒内有多个操作时用于排序。在没有使用 t 的情况下,i 没有作用。 |
类型检查
使用 $type 查询运算符或检查对象构造函数以确定类型。
JavaScript 的 typeof 运算符返回通用的值,如 number 或 object,而不是更具体的 Int32 或 ObjectId。
JavaScript 的 instanceof 运算符不可靠。例如,instanceof 将服务器响应中的BSON值分配给与用户提供的值不同的基类。
有关使用示例,请参阅 使用 $type() 进行类型检查 和 使用构造函数进行类型检查。
示例
将日期作为字符串返回
要返回日期字符串,请使用Date()方法,如下例所示
var myDateString = Date();
要打印变量值,在shell中输入变量名,如下
myDateString
结果是myDateString的值
Wed Dec 19 2012 01:03:25 GMT-0500 (EST)
要验证类型,使用typeof运算符,如下
typeof myDateString
操作返回string。
返回Date
mongosh使用ISODate辅助器包装了Date类型的对象;然而,这些对象仍然是Date类型。
以下示例同时使用了new Date()构造函数和ISODate()构造函数来返回Date对象。
var myDate = new Date(); var myDateInitUsingISODateWrapper = ISODate();
您也可以使用new运算符与ISODate()构造函数。
要打印变量值,在shell中输入变量名,如下
myDate
结果是myDate的Date值被ISODate()辅助器包装
ISODate("2012-12-19T06:01:17.171Z")
要验证类型
var myDate = ISODate("2021-03-21T06:00:00.171Z") Object.prototype.toString.call(myDate) === "[object Date]"
操作返回true。
数值类型
考虑types集合
{ _id: 1, value: 1, expectedType: 'Int32' }, { _id: 2, value: Long("1"), expectedType: 'Long' }, { _id: 3, value: 1.01, expectedType: 'Double' }, { _id: 4, value: Decimal128("1.01"), expectedType: 'Decimal128' }, { _id: 5, value: 3200000001, expectedType: 'Double' }
此表显示了对应 <QUERY> 的 db.types.find( <QUERY> ) 命令的结果。类型名称和别名可在 BSON 类型 页面上找到。
查询 | 结果 | |||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| | |||||||||||||||||||||||||||||||
| | |||||||||||||||||||||||||||||||
| | |||||||||||||||||||||||||||||||
| | |||||||||||||||||||||||||||||||
| | |||||||||||||||||||||||||||||||
| | |||||||||||||||||||||||||||||||
| |
查询 { "value": 1.01 } 隐式搜索 1.01 的 Double 表示形式。文档 _id: 4 是 Decimal128 类型,因此未被选中。
注意,然而,{ "value": 1 } 返回了 Int32 和 Long 类型。
默认数值类型一致性
考虑 typeExample 集合。此集合包含两个相同的文档,{ "a": 1 }。第一个文档是在旧版 mongo shell 中创建的,第二个文档是在 mongosh 中创建的。
我们可以在聚合管道中使用 $type 操作符来查看每个 shell 中分配的类型。
db.typeExample.aggregate( [ { $project: { "valueType": { "$type": "$a" }, "_id": 0 } } ] )
在旧版 mongo shell 中创建的第一个文档中,值被存储为 double 类型。在 mongosh 文档中,值被存储为类型 int。
[ { valueType: 'double' // inserted in legacy mongo shell }, { valueType: 'int' // inserted in mongosh } ]
为新的文档添加时间戳
使用不带参数的 Timestamp() 插入多个文档,并使用默认设置
db.flights.insertMany( [ { arrival: "true", ts: Timestamp() }, { arrival: "true", ts: Timestamp() }, { arrival: "true", ts: Timestamp() } ] )
运行 db.flights.find({}) 来查看时间戳。注意,尽管所有三个条目都是在同一秒中标记的,但每个条目的间隔都增加了。
[ { _id: ObjectId("6114216907d84f5370391919"), arrival: 'true', ts: Timestamp({ t: 1628709225, i: 1 }) }, { _id: ObjectId("6114216907d84f537039191a"), arrival: 'true', ts: Timestamp({ t: 1628709225, i: 2 }) }, { _id: ObjectId("6114216907d84f537039191b"), arrival: 'true', ts: Timestamp({ t: 1628709225, i: 3 }) } ]
创建自定义时间戳
使用自定义参数插入具有特定 时间戳 的多个文档。
此操作将三个文档插入到 flights 集合中,并使用 UNIX 纪元 值 1627811580 将 ts 时间设置为 2021 年 8 月 1 日 9:53 GMT。
db.flights.insertMany( [ { arrival: "true", ts: Timestamp(1627811580, 10) }, { arrival: "true", ts: Timestamp(1627811580, 20) }, { arrival: "true", ts: Timestamp(1627811580, 30) } ] )
生成的文档如下所示
[ { _id: ObjectId("6123d8315e6bba6f61a1031c"), arrival: 'true', ts: Timestamp({ t: 1627811580, i: 10 }) }, { _id: ObjectId("6123d8315e6bba6f61a1031d"), arrival: 'true', ts: Timestamp({ t: 1627811580, i: 20 }) }, { _id: ObjectId("6123d8315e6bba6f61a1031e"), arrival: 'true', ts: Timestamp({ t: 1627811580, i: 30 }) } ]
使用 $type() 进行类型检查
$type 查询运算符接受一个字符串别名或对应数据类型的数字代码。有关 BSON 数据类型及其对应数字代码的列表,请参阅 BSON 类型。
例如,这些对 Decimal128 类型的检查是等效的
db.types.find( { "value": { $type: "decimal" } } ) db.types.find( { "value": { $type: 19 } } )
使用构造函数进行类型检查
检查对象 constructor 以确定类型。例如,db.collection.find() 的输出是一个 Cursor。
var findResults = db.housing.find({"multiUnit": true} ) findResults.constructor.name // Returns the type