欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

程序员文章站 2022-06-07 19:01:38
今天在用mongoexport导出满足一定条件下的数据时,遇到了一个报错,现纪录下来,并且针对此错误对MongoDB 的 数字类型 做了进一步的学习。 背景 及 报错信息 今天接到一个业务需求,需要从MongoDB 数据库 order集合中导出符合以下条件的数据: db.qqwj_order.fin ......

今天在用mongoexport导出满足一定条件下的数据时,遇到了一个报错,现纪录下来,并且针对此错误对mongodb 的 数字类型 做了进一步的学习。

背景 及 报错信息 

今天接到一个业务需求,需要从mongodb 数据库 order集合中导出符合以下条件的数据:

 

db.qqwj_order.find({"source":numberint("21"),"batch":"支付中的订单提醒:2018/9/5","msgcontent":/还未完成在线付款/})

 

通过mongodb 客户端工具 【nosqlbooster for mongodb】查询检查,语句执行正常,显示相应记录数为 15265。

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

导出数据使用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

错误截图如下:

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

 

错误推断及测试

 

因为报错信息中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

 

执行结果为

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

结果表明修改后,数据成功导出

错误解析与原理探究

 

为什么通过查询器查看,数据就是     "source" : numberint("21"),但是在shell 中的执行导出命令写成"source" : numberint("21") 就会报错。而一定要转换为"source":21

查询器查询出的source字段显示:

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

明明就是 "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 方式 插入测试数据

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

通过 shell方式插入测试数据

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

 

通过$type 去查看插入的数据类型

 

1》执行db.numbers.find({n:{$type:1}})  // type 为 double;查询type 为 double的数据

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

以上查询结果显示,不管是通过客户端还是shell,当数字不指明数据类型时,插入的数字数据默认都是double。

 

 2》执行命令 db.numbers.find({n:{$type:16}})  // type 为 32-bit integer ;查询type 为 32-bit integer的数据

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

以上查询表名,不管通过客户端还是shell,指定的numberint(5) 还是numberint('5‘) 后台都转成统一32-bit integer 类型存储了。

 

 3》执行命令 db.numbers.find({n:{$type:18}})  // type 为 64-bit integer 查询type 为 64-bit integer的数据

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

 

以上查询表名,不管通过客户端还是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 

MongoDB 执行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 

执行成功的导出命令是:

/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")。嘻嘻 》》》》版本不同而已。

旧版本(部分)的显示

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

新版本(例如nosqlbooster4mongo-4.7.1)的显示

MongoDB 执行mongoexport时异常及分析(关于数字类型的查询)

p.s  2  :在存储数字数据时,到底会存储为何种数据类型,其实和语言的的驱动有关。例如在ruby 和 python 语言里在序列化整数时,驱动会自动确定是否编码为32-bit integer 还是 64-bit integer;shell 需要显示指定才可以。