Loading

Mongodb 使用需要避免的"坑"

前提

mongodb版本是 4.4.14

root@8163d7b355e7:/# mongo --version
MongoDB shell version v4.4.14
Build Info: {
    "version": "4.4.14",
    "gitVersion": "0b0843af97c3ec9d2c0995152d96d2aad725aab7",
    "openSSLVersion": "OpenSSL 1.1.1f  31 Mar 2020",
    "modules": [],
    "allocator": "tcmalloc",
    "environment": {
        "distmod": "ubuntu2004",
        "distarch": "x86_64",
        "target_arch": "x86_64"
    }
}
root@8163d7b355e7:/# 

建立一张demo表并,初始化两条int32类型的数据

db.demo.insert({"params1" : NumberInt(1),"params2" : NumberInt(1)})

如下

mongodb bson类型查询表

bson 每个数据类型都有一个相应的数字和字符串别名,可以与$ type运算符一起使用BSON类型查询文档。

Type Number Alias Notes
Double 1 double
String 2 string
Object 3 object
Array 4 array
Binary data 5 binData
Undefined 6 undefined
ObjectId 7 objectId
Boolean 8 bool
Date 9 date
Null 10 null
Regular Expression 11 regex
DBPointer 12 dbPointer
JavaScript 13 javascript
Symbol 14 symbol
JavaScript (with scope) 15 javascriptWithScope
32-bit integer 16 int
Timestamp 17 timestamp
64-bit integer 18 long
Min key -1 minKey
Max key 127 maxKey

mongo shell 更改类型的问题

开始时初始化数据生成了一条数据,分别为 params1(1) int32, params2(2) int32

现在如果想把params1的数据改为int64一般使用的做法是,通过mongodb客户端,执行以下命令

根据bson类型查询表找到int32类型的数据,循环更新为int64

db.demo.find({"params1" : {$type : 16}}).forEach(function(x) {
	x.params1 = NumberLong(x.params1);
	db.demo.save(x);
})

执行结果如下

params1 的类型被改成了Int64,但是并没有更改params2的数据,params2却从Int32变成了Double类型。

分析如下

导致该情况出现的原因是因为mongo shell 是js实现的,而js不是一个类型化语言。

通过查询mongodb官方文档
https://www.mongodb.com/docs/manual/core/shell-types/?_ga=2.43697382.294185521.1652615680-1710587817.1652615680

得到如下解释

The mongo shell treats all numbers as 64-bit floating-point double values by default.

意思是默认情况下,mongo shell 将所有数字视为int64 和 double类型,也就是说,通过mongo shell更改类型 除了int64 和 double类型的数字数据都会自动转换成double类型。

解决方案

更改类型建议使用后端驱动程序进行更改,而不是通过mongo shell。

$where 自查询无法比较int64和int64类型的数据

当前数据库有一条数据,params1 和 params2

执行语句

db.demo.find({"$where" : "this.params1 == this.params2"})

返回结果如下

  • params1类型int32,params2类型int32 返回有值
  • params1类型int64,params2类型int32 返回有值
  • params1类型double,params2类型int32 返回有值
  • params1类型double,params2类型int64 返回有值
  • params1类型int64,params2类型int64 返回为空

得出结论

在$where 子查询中,只有int64和int64之间无法比较,其他类型之间可以相互比较,所以慎用$where子查询。

posted @ 2022-05-15 21:42  小博。  阅读(252)  评论(0编辑  收藏  举报