MongoDB 基础系列十四:mongo Shell 之数据类型

前言

此篇博文是 Mongdb 基础系列之一;

本文为作者的原创作品,转载需注明出处;

Types

Date

mongo shell 提供了多种方法来返回 date,可以返回 string 或者 Date Object:

  • Date() 以 string 的形式返回当前的日期
  • new Date() 通过 ISODate() 封装返回一个 Date object;
  • ISODate() 通过 ISODate() 封装返回一个 Date object;

在 mongo 内部,Date 对象是基于从 Unix epoch( 1970-01-01 ) 的一串 64 bit 的整数数值;

Return Date as String

如果想要得到 date 的 string 类型数值,使用 Date() 方法;比如下面的例子,在 mongo shell 中执行;

1
2
3
> var myDateString = Date();
> myDateString
Mon Jul 24 2017 15:55:42 GMT+0800 (CST)

可见,myDateString 返回的就是一个 string 字符串;

Return Date

下面的这个例子分别显示了通过 new Date()ISODate() 方法返回的通过 ISODate 进行封装以后的 Date objects; 同样,在 mongo shell 中执行;

1
2
> var myDate = new Date();
> var myDateInitUsingISODateWrapper = ISODate();

上述的例子中,也可以使用 new ISODate()

输出,

1
2
3
4
> myDate
ISODate("2017-07-24T07:59:12.929Z")
> myDateInitUsingISODateWrapper
ISODate("2017-07-24T08:02:16.781Z")

可见 myDatemyDateInitUsingISODateWrapper 返回的都是由 ISODate 包裹的 Date 对象;我们可以通过 instance of 来对各个 Date 对象进行类型验证;

1
2
3
4
> myDate instanceof Date
true
> myDateInitUsingISODateWrapper instanceof Date
true

ObjectId

mongo shell 提供了 ObjectId() 封装类来封装 ObjectId 类型,可以通过下述方式在 mongo shell 中生成 ObjectId,

1
> new ObjectId

在我本地测试,

1
2
3
> var id = new ObjectId
> id
ObjectId("5975aae8cb568ef80824a9b9")

可见,输出的正式一个 ObjectId() 对象;更多相关内容查看 Reference ObjectId

NumberLong

默认情况下,mongo shell 将所有的 numbers 都当做浮点数来进行处理;mongo shell 提供了 NumberLong() 包装器来处理 64-bit 的整数;

可以通过 string 来初始化,

1
> NumberLong("2090845886852")

来看看如下的对 NumberLong 类型的数据执行操作的例子,

1
2
3
4
5
> db.collection.insertOne( { _id: 10, calc: NumberLong("2090845886852") } )
> db.collection.updateOne( { _id: 10 },
{ $set: { calc: NumberLong("2555555000000") } } )
> db.collection.updateOne( { _id: 10 },
{ $inc: { calc: NumberLong(5) } } )

首先,在 collection 中新增一个 document,_id = 10,calc = NumberLong(…);然后,对其重新进行赋值;最后,对 calc 递增 5;验证一下结果,

1
2
> db.collection.findOne( { _id: 10 } )
{ "_id" : 10, "calc" : NumberLong("2555555000005") }

可以看到,我们已经对 calc 字段值成功的递增了 5;并且 calc 依然是 NumberLong 类型;

不过,需要注意的是,如果在使 $inc 来为上面的字段 calc 进行递增操作的时候,如果使用的是 float 类型的数字,那么,递增以后,calc 的值将会改变为 float 类型;比如,

1
2
> db.collection.updateOne( { _id: 10 },
{ $inc: { calc: 5 } } )

注意,默认情况下,mongo shell 将所有的数字当做 float 类型来处理,所这里,5 表示 float 类型;继续验证一下,

1
2
> db.collection.findOne( { _id: 10 } )
{ "_id" : 10, "calc" : 2555555000010 }

可以看到,calc 已经从 NumberLong 类型转变为了 float 类型;

NumberInt

The mongo shell treats all numbers as floating-point values by default. The mongo shell provides the NumberInt() constructor to explicitly specify 32-bit integers.

NumberDecimal

New in version 3.4.

The mongo shell treats all numbers as 64-bit floating-point double values by default. The mongo shell provides the NumberDecimal() constructor to explicitly specify 128-bit decimal-based floating-point values capable of emulating decimal rounding with exact precision. This functionality is intended for applications that handle monetary data, such as financial, tax, and scientific computations.

可以通过 string 来构造 decimal

1
2
> NumberDecimal("1000.55")
NumberDecimal("1000.55")

可以看到,返回的也就是 NumberDecimal(“1000.55”) ;

可以通过 double 来构造 decimal

1
2
> NumberDecimal(1000.55)
NumberDecimal("1000.55000000000")

也可以通过 double 来构造 decimal,可以看到,返回的 decimal 补全了精度;在看一个特殊的情况,

1
2
> NumberDecimal(9999999.4999999999)
NumberDecimal("9999999.50000000")

比较

需要注意的是,原生的 double 型数值不能与对应的 decimal 进行匹配;比如,我们有如下这个例子,

1
2
3
4
5
{ "_id" : 1, "val" : NumberDecimal( "9.99" ), "description" : "Decimal" }
{ "_id" : 2, "val" : 9.99, "description" : "Double" }
{ "_id" : 3, "val" : 10, "description" : "Double" }
{ "_id" : 4, "val" : NumberLong(10), "description" : "Long" }
{ "_id" : 5, "val" : NumberDecimal( "10.0" ), "description" : "Decimal" }

下面是通过 db.numbers.find(<query>) 方法进行查询的结果,

为什么会得到上面这个结果呢?

第一个查询 { “val”: 9.99 } 隐式的表示了是通过 double 类型来进行查询的,所以,它不能与 decimal 9.99 相匹配;

第二个查询,表示是通过 decimal 来进行查询,显然,double 与 decimal 不匹配;

后两个查询,注意,是var不是"var"的方式,将会试图去匹配所有类型的数值,不管是 decimal 还是 double 还是什么?以第三个查询为例,当试图查询 double 类型 10 的时候,同时会将其转换为对应的 decimal 数值来进行匹配;

查询匹配 dcimal type

To test for decimal type, use the $type operator with the string alias “decimal” or 19, the numeric code for the decimal type.

1
> db.inventory.find( { price: { $type: "decimal" } } )

Check Types

instanceof

instanceof 返回一个 boolean 值来表示某个值是否是某个类型的实例;比如,我们想要检测某个 document 对象的 _id 字段值是否是 ObjectId 的实例,

1
mydoc._id instanceof ObjectId

将会返回 true

typeof

typeof 返回一个 field 的类型;

同样是上面这个例子,只是这次,我们换成了 typeof

1
typeof mydoc._id

这个例子中,将会返回 object type 而不是 ObjectId 类型,因为 objectObjectId 的超类;