关于mongodb:mongodb-mongo常用字段类型

4次阅读

共计 4953 个字符,预计需要花费 13 分钟才能阅读完成。

1、json 和 bson

JSON

JSON 是一种简略的数据表示形式,它易于了解、易于解析、易于记忆。但从另一方面来说,因为只有 null、布尔、数字、字符串、数组和对象这几种数据类型,所以 JSON 有肯定局限性。例如,JSON 没有日期类型,JSON 只有一种数字类型,无奈辨别浮点数和整数,更别说辨别 32 为和 64 位数字了。再者,JSON 无奈示意其余一些通用类型,如正则表达式或函数。

BSON

BSON(Binary Serialized Document Format)是一品种 JSON 的二进制模式的存储格局,简称 Binary JSON。它和 JSON 一样,反对内嵌的文档对象和数组对象,然而 BSON 有 JSON 没有的一些数据类型,如 Date 和 BinData 类型。它反对上面数据类型。每个数据类型对应一个数字,在 MongoDB 中能够应用 $type 操作符查看相应的文档的 BSON 类型

MongoDB 毋庸申明数据类型,全自动匹配

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

Type Number Alias Notes
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 (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” New in version 3.4.
Min key -1 “minKey”
Max key 127 “maxKey”

2、数据类型

2.1、double 类型

mongo shell 客户端默认将数字看成浮点数。

2.2、64-bit integer(long)

BSON 有两种整型数据类型:32 位有符号整型数据(INT); 64 位有符号型整型数据(LONG)

转换函数为 NumberLong(),

2.3、32-bit integer(int)

32-bit integer(int)和 64-bit integer(long)差不多,不同的是,其转换函数由 NumberLong()变成了 NumberInt(),其承受的参数,也当成 string 类型来解决。

2.4、decimal

Decimal 这个数据类型是在 Mongo 3.4 才开始引入的。新增 Decimal 数值类型次要是为了记录、解决货币数据,例如 财经数据、税率数据等。有时候,一些科学计算也采纳 Decimal 类型。

因为 mongo shell 默认将数字当成 double 类型,所以也是须要显式的 转换函数 NumberDecimal(),其承受参数是 string 值。

mongos> db.testnum01.insert({_id:231,calc:NumberDecimal("1000.55")})

阐明:

int/long/decimal,参数承受类型是 string,如果是数字(默认是 double 类型)也能够,然而有精度失落的危险,会把数字变成 15 位(小数点不计算在内)

2.5 数字类型相加测试

以上 4 中都为数字类型,进行 decimal 与个类型数字的相加测试,如果如下:

Decimal 与 decimal/int/long 类型相加,小数位不变;

decimal 与 double 类型相加,小数位会变成 14 位。

mongos> db.testnum01.find({_id:231})
{"_id" : 231, "calc" : NumberDecimal("1004.55") }
mongos> db.testnum01.updateOne({_id:231},{$inc:{calc:2}})
{"acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1}
mongos> db.testnum01.find({_id:231})
{"_id" : 231, "calc" : NumberDecimal("1006.55000000000000") }

2.6 object ID

相似于惟一的主键,蕴含 12 个字节:总共有 24 位 16 进制数形成,也就是 12 个字节。

{"_id" : ObjectId("5f2a22f7aa56fc2fc978b159"), "calc" : 123456789012345680 }
5f2a22f7 aa56fc 2fc9 78b159
#"5f2a22f7" 代指的是 unix 工夫戳, 这条数据的产生工夫
#"aa56fc" 代指某台机器的机器码, 存储这条数据时的机器编号
#"2fc9" 代指过程 ID, 多过程存储数据的时候, 十分有用的
#"78b159" 代指随机数, 这里要留神的是, 随机数的数字可能会呈现反复, 不是惟一的
#以上四种标识符拼凑成世界上惟一的 ObjectID
#只有是反对 MongoDB 的语言, 都会有一个或多个办法, 对 ObjectID 进行转换
#能够失去以上四种信息

#留神: 这个类型是不能够被 JSON 序列化的
这是 MongoDB 生成的相似关系型 DB 表主键的惟一 key,具体由 24 个 bit 组成:0- 8 字节是 unix 工夫戳,
9-14 字节的机器码,示意 MongoDB 实例所在机器的不同;15-18 字节的过程 id,示意雷同机器的不同 MongoDB 过程。19-24 字节是随机数

因为 ObjectId 中保留了创立的工夫戳,所以你不须要为你的文档保留工夫戳字段,
能够通过 ”getTimestamp()” 来获取文档的创立工夫戳, 返回工夫戳

-- 返回工夫戳
mongos> ObjectId("5f2a22f7aa56fc2fc978b159").getTimestamp()
ISODate("2020-08-05T03:09:43Z")
-- 返回字符串
mongos> ObjectId("5f2a22f7aa56fc2fc978b159").str
5f2a22f7aa56fc2fc978b159

2.7 string

utf- 8 字符串,记住肯定是 utf- 8 字符串

2.8 arrays

数组或者列表,多个值存储到一个键 (list)

"hobby" : ["羽毛球","足球","篮球"]

2.9 Object 字典

"course" : {"name" : "MongoDB","price" : 1000}

2.10 Null

空数据类型 , 一个非凡的概念,None Null

2.11 timetamp 工夫戳

"date" : 1528183743111

2.12 data

存储以后日期或工夫格局

 "date" : ISODate("2019-01-05T15:28:33.705+08:00")

3、mongo 中应用大整数精度失落问题

Mongo shell 中应用大整数字面量,但默认整数字面量类型却是双精度浮点数,导致失落精度

  • 问题形容:

通过 mongo shell 插入或更新一个大整数(长度约大于等于 16 位数字)时,例如:

mongos> db.testnum01.insert([{_id:100,calc:12345678901111111111},{_id:101,calc:NumberLong("1234567890123456789")}])

实际上插入的是

> db.testnum01.find()
{"_id" : 100, "calc" : 12345678901111112000}
{"_id" : 206, "calc" : 12345678902222221000}
{"_id" : 207, "calc" : 12345678903333333000}
{"_id" : 101, "calc" : NumberLong("1234567890123456789") }
  • 剖析:

因为 mongo shell 实际上是一个 js 引擎,而在 javascript 中,根本类型中并没有 int 或 long,所有整数字面量实际上都以双精度浮点数示意(IEEE754 格局)。64 位的双精度浮点数中,理论是由 1bit 符号位,11bit 的阶码位,52bit 的尾数位形成。

11bit 的余 -1023 阶码使得双精度浮点数提供大概 -1.7E308~+1.7E308 的范畴,52bit 的尾数位大略能示意 15~16 位数字(局部 16 位长的整数曾经超出 52bit 能示意的范畴)。

所以当咱们在 mongo shell 中间接应用整数时,实际上它是以 double 示意的,而当这个整数字大概超过 16 位数字时,就可能产生有些整数无奈准确示意的状况,只能应用一个靠近能示意的整数来代替。如下面例子中,存入 20 位的数字,实际上能无效示意的数字只有 16 位,另外 4 位产生精度失落的状况。

  • 解决办法:

应用 NumberLong()函数结构长整型的类型,记住传入的参数肯定要加双引号,否则应用整数的话又会被当做 double 而可能失落精度。

留神:long 类型:64bit,8 字节有符号型,最大可存 2^63-1=9223372036854775807

超过 64 位可存储为字符串:> db.testnum01.insert({_id:222,calc:”12345678901234567890″})

mongos> db.testnum01.insert({_id:200,calc:NumberLong(1234567890123456789)})
mongos> db.testnum01.insert({_id:201,calc:NumberLong("1234567890123456789")})
mongos> db.testnum01.find()
{"_id" : 200, "calc" : NumberLong("1234567890123456768") }   // 最初 2 位精度不对
{"_id" : 201, "calc" : NumberLong("1234567890123456789") }

mongos> db.testnum01.insert({_id:202,calc:NumberLong("9223372036854775808")})    -- 无奈写入
2020-08-05T13:39:48.422+0800 E QUERY     Error: could not convert string to long long :
@(shell):1:35
mongos> db.testnum01.insert({_id:202,calc:NumberLong("9223372036854775807")})   -- 能够写入
WriteResult({"nInserted" : 1})
mongos>

留神,除了在 mongo shell(javascript 语言环境中),在其余不反对长整型而默认应用浮点数代替示意的编程语言中也会存在相似问题,操作时肯定要注意。

4、判断某字段类型 / 长度

// 字段类型为 2(string),示意有此字段,或者用: $exists: true,长度大于 100
mongos> db.testnum01.find({calc: {$type:2,$regex: /^.{100,}$/ }});
mongos> db.testnum01.find({calc: {$exists: true, $regex: /^.{10,}$/ }});
// 查问字段类型为 long、double 的
mongos> db.testnum01.find({calc:{$type:"double"}})    --db.testnum01.find({calc:{$type:1}})
mongos> db.testnum01.find({calc:{$type:"long"}})    --db.testnum01.find({calc:{$type:18}})

正文完
 0