MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)
2018-09-06 22:01
507 查看
今天在用mongoexport导出满足一定条件下的数据时,遇到了一个报错,现纪录下来,并且针对此错误对MongoDB 的 数字类型 做了进一步的学习。
db.qqwj_order.find({"Source":NumberInt("21"),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/})
通过MongoDB 客户端工具 【NoSQLBooster for MongoDB】查询检查,语句执行正常,显示相应记录数为 15265。
导出数据使用mongoexport命令,执行命令如下:
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{ "Source":NumberInt("21"),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
但是执行报错:
XXX is not valid JSON: json: cannot unmarshal string into Go value of type json.NumberInt
错误截图如下:
结果将导出命令中的 NumberInt("21") 直接替换为 21 ,再次执行。
执行命令为 :
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source":21,"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
执行结果为
结果表明修改后,数据成功导出。
查询器查询出的Source字段显示:
明明就是 "Source" : NumberInt("21"),为什么复制到shell,执行报错???
回头看,找原理。我们知道目前MongoDB 支持4中数据类型。
double
32-bit integer
64-bit integer
Decimal (New in version 3.4.)
在MongoDB客户端可以执行查询,但是在shell中无法执行导出,那么会不会和这两种工具有关?会不会和插入的NumberInt(数字) 还是NumberInt('数字‘)有关?
下面对假设进行验证测试。
通过 NoSQLBooster for MongoDB 方式 插入测试数据
通过 shell方式插入测试数据
通过$type 去查看插入的数据类型
1》执行db.numbers.find({n:{$type:1}}) // Type 为 Double;查询Type 为 Double的数据
以上查询结果显示,不管是通过客户端还是shell,当数字不指明数据类型时,插入的数字数据默认都是Double。
2》执行命令 db.numbers.find({n:{$type:16}}) // Type 为 32-bit integer ;查询Type 为 32-bit integer的数据
以上查询表名,不管通过客户端还是shell,指定的NumberInt(5) 还是NumberInt('5‘) 后台都转成统一32-bit integer 类型存储了。
3》执行命令 db.numbers.find({n:{$type:18}}) // Type 为 64-bit integer 查询Type 为 64-bit integer的数据
以上查询表名,不管通过客户端还是shell,指定的NumberLong(5) 还是NumberLong('5') 后台都转成统一64-bit integer 类型存储了。
以上的测试说明,当我们在存储数字数据时会自动转储(不管什么客户端工具,是shell还是 【NoSQLBooster for MongoDB】,不管 NumberLong(5) 还是NumberLong('5');NumberInt(5) 还是NumberInt('5‘))。
有点糊涂了吧? 如此这样,那为什么 在查询是报错呢?
回头再看错误提示:XXX is not valid JSON: json: cannot unmarshal string into Go value of type json.NumberInt。
其意思是shell 认为我们把一个字符类型的数据传给了 json.NumberInt。
那我如果将导出命令中的 NumberInt("21") 将 换成 NumberInt(21)
执行命令为 :
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source": NumberInt(21),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
执行也成功。
执行失败的导出命令是:
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{ "Source":NumberInt("21"),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
执行成功的导出命令是:
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source":21,"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
和
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source": NumberInt(21),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
三个导出命令不同的地方已用红色字体标注。
P.S 1 :后来作者深究了一下,为什么同样的查询,通样的查询结果,有的显示 "n" : 5 ; 有的显示 "n" : NumberInt("5")。嘻嘻 》》》》版本不同而已。
旧版本(部分)的显示
新版本(例如nosqlbooster4mongo-4.7.1)的显示
P.S 2 :在存储数字数据时,到底会存储为何种数据类型,其实和语言的的驱动有关。例如在Ruby 和 Python 语言里在序列化整数时,驱动会自动确定是否编码为32-bit integer 还是 64-bit integer;shell 需要显示指定才可以。
背景 及 报错信息
今天接到一个业务需求,需要从MongoDB 数据库 order集合中导出符合以下条件的数据:db.qqwj_order.find({"Source":NumberInt("21"),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/})
通过MongoDB 客户端工具 【NoSQLBooster for MongoDB】查询检查,语句执行正常,显示相应记录数为 15265。
导出数据使用mongoexport命令,执行命令如下:
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{ "Source":NumberInt("21"),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
但是执行报错:
XXX is not valid JSON: json: cannot unmarshal string into Go value of type json.NumberInt
错误截图如下:
错误推断及测试
因为报错信息中NumberInt 关键字,此时去看我们的查询条件正好也有此关键字,所以推测 是不是这个问题。结果将导出命令中的 NumberInt("21") 直接替换为 21 ,再次执行。
执行命令为 :
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source":21,"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
执行结果为
结果表明修改后,数据成功导出。
错误解析与原理探究
为什么通过查询器查看,数据就是 "Source" : NumberInt("21"),但是在shell 中的执行导出命令写成"Source" : NumberInt("21") 就会报错。而一定要转换为"Source":21查询器查询出的Source字段显示:
明明就是 "Source" : NumberInt("21"),为什么复制到shell,执行报错???
回头看,找原理。我们知道目前MongoDB 支持4中数据类型。
double
32-bit integer
64-bit integer
Decimal (New in version 3.4.)
在MongoDB客户端可以执行查询,但是在shell中无法执行导出,那么会不会和这两种工具有关?会不会和插入的NumberInt(数字) 还是NumberInt('数字‘)有关?
下面对假设进行验证测试。
通过 NoSQLBooster for MongoDB 方式 插入测试数据
通过 shell方式插入测试数据
通过$type 去查看插入的数据类型
1》执行db.numbers.find({n:{$type:1}}) // Type 为 Double;查询Type 为 Double的数据
以上查询结果显示,不管是通过客户端还是shell,当数字不指明数据类型时,插入的数字数据默认都是Double。
2》执行命令 db.numbers.find({n:{$type:16}}) // Type 为 32-bit integer ;查询Type 为 32-bit integer的数据
以上查询表名,不管通过客户端还是shell,指定的NumberInt(5) 还是NumberInt('5‘) 后台都转成统一32-bit integer 类型存储了。
3》执行命令 db.numbers.find({n:{$type:18}}) // Type 为 64-bit integer 查询Type 为 64-bit integer的数据
以上查询表名,不管通过客户端还是shell,指定的NumberLong(5) 还是NumberLong('5') 后台都转成统一64-bit integer 类型存储了。
以上的测试说明,当我们在存储数字数据时会自动转储(不管什么客户端工具,是shell还是 【NoSQLBooster for MongoDB】,不管 NumberLong(5) 还是NumberLong('5');NumberInt(5) 还是NumberInt('5‘))。
有点糊涂了吧? 如此这样,那为什么 在查询是报错呢?
回头再看错误提示:XXX is not valid JSON: json: cannot unmarshal string into Go value of type json.NumberInt。
其意思是shell 认为我们把一个字符类型的数据传给了 json.NumberInt。
那我如果将导出命令中的 NumberInt("21") 将 换成 NumberInt(21)
执行命令为 :
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source": NumberInt(21),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
执行也成功。
结论
说了很多总结下:执行失败的导出命令是:
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{ "Source":NumberInt("21"),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
执行成功的导出命令是:
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source":21,"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
和
/data/mongodb/mongobin344/bin/mongoexport -h 172.X.X.XXX --port 端口 --db 数据库 -u 账号 -p '密码' --authenticationDatabase 认证数据库 --type=csv -c qqwj_order -f MsgContent,REC_CreateTime -q '{"Source": NumberInt(21),"Batch":"支付中的订单提醒:2018/9/5","MsgContent":/还未完成在线付款/}' -o /data/mongodb_back/sms.csv
三个导出命令不同的地方已用红色字体标注。
P.S 1 :后来作者深究了一下,为什么同样的查询,通样的查询结果,有的显示 "n" : 5 ; 有的显示 "n" : NumberInt("5")。嘻嘻 》》》》版本不同而已。
旧版本(部分)的显示
新版本(例如nosqlbooster4mongo-4.7.1)的显示
P.S 2 :在存储数字数据时,到底会存储为何种数据类型,其实和语言的的驱动有关。例如在Ruby 和 Python 语言里在序列化整数时,驱动会自动确定是否编码为32-bit integer 还是 64-bit integer;shell 需要显示指定才可以。
相关文章推荐
- MongoDB执行mongoexport时的异常及分析(数字类型的查询)
- SQLServer\framework启动报异常:Module的类型初始值设定项引发异常 [转]QQ空间、新浪微博、腾讯微博等一键分享API链接代码 window下 mongodb快速安装 数据表查询所有子/父节点 C#学习笔记1
- 关于用Hibernate执行sql查询,字符字段类型只返回第一个字节的问题
- 关于mongodb查询数据,数值类型查找不到数据的问题
- 关于mongoDB查询类型为ObjectId的SQL
- 第三章:分析基本查询的文本和XML执行计划
- 如何使用SQLPLUS分析SQL语句(查询执行计划跟踪)
- 关于VB提示ByRef参数类型不符的分析
- 关于Android中处理崩溃异常和分析日志的两种思路
- PostgreSQL源码分析(2)– 常用数据类型/SQL语句的解释和执行
- Hadoop2.7.3 mapreduce(二)类型匹配异常解决方案及源码分析
- 关于数据存储类型的一点分析
- Mybatis 查询结果 类型转换异常错误 ResultSetWrapper 转换类型错误 ,
- 查询一个int类型的变量(数字)是否在一个字符串里边(逗号分隔的)以及 sqlif 与case
- 【MongoDB】6.关于MongoDB存储文件的 命令执行+代码执行
- MongoDB干货系列2-MongoDB执行计划分析详解(1)
- 关于hibernate查询sqlserver时char类型只能取第一个字符的问题
- SpringMVC(关于HandlerMapping执行流程原理分析)
- Mongodb源码分析--查询结果集封装
- 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }