mongodb采坑之路-number/numberlong
mongodb作为优秀的文件存储数据库,既能向redis一样实现轻量级的缓存,又能作为百万、千万级的数据储存,还有灵活的NOSQL及内置mapreduce功能,当然在多节点分片应用的场景下,又能提供绝对高于redis的性能优势,在项目应用中已经越来越多。
从15年左右开始逐步接触mongodb,到现在已经有4-5年的使用经验了,然而今天碰到的这个大坑,硬生生的的折腾了我好几个小时。。。。下面把这段囧经历分享一下,让大家开心一下。
背景
目前公司有需求需要重构一个项目,其中包括数据库的重构以及在项目中增加缓存的使用,当然由于数据级别比较大,而且涉及政府项目中间很可能过网闸,为了最大限度的提升前端应用响应速度,这里我选用mongodb在网闸前段应用增加缓存,避免大量数据通过网闸进行交互,以此提升高并发性能。
缓存信息之一即是用户表,原用户表采用了***19位数字ID***。
PS:为啥是19位数字ID咱表示也不知道
啧啧啧~如下图,那个123开头的就是之前的19位数字ID,这个ID有
那么长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长
接下来。根据ID查询数据。
那么我们写入第一个查询语句。=就是这个比较长的啦。。
db.personHealthCode.find({_id:1234386662595891200});
不出所料-直接就查出来了。。
那么我们写入第二个查询语句。=当然就是这个比较短的了。。
db.personHealthCode.find({_id:39529165196514388});
**WTF~~~~~~!!!你看的没错。。啥也没有。。**
没办法,我开启了怀疑模式。。。难道这个ID不是NUMBER?
于是乎
db.personHealthCode.find({_id:"39529165196514388"});
db.personHealthCode.find({"_id":39529165196514388});
db.personHealthCode.find({"_id":"39529165196514388"});
加的我连代码都不会写了。。。。。然而依然查不出来。。。。。。
再次于是乎😅😅😅😅😅那么就来看看这个字段到底是啥数据类型吧*****
直接查询ID类型是number的,妥妥的有值,然后又查ID大于小于一个既有值之间的数据。依然妥妥的有值…………
然后表示现在我心理慌的一B啊。。。😀😀😀😀😀😀
继续发动脑细胞 ヾ(o◕∀◕)ノヾ仔细的想。。。。这TM到底是个什么数据类型。。。。怎么就查不到。。
。。。再次确认是NUMBER没有错~!!!!!!!!!!!!!!!!!!!
到此为止,我已经深深的怀疑,这是数据库的BUG!!!BUG!!!!,因为目前使用的是3.6社区版本,于是俺准备找个4.X版🙏🙏🙏🙏🙏🙏🙏,保佑。。4.X可千万别出问题。。把数据搞进去试试。。。
那么第一步。。。备份数据吧。。
于是乎。。让我发现了一个惊天😱😱😱😱😱😱😱😱的秘密 。。这货居然是numberlong。。那么推断一下,,,直接强转就完了呗😁。。。
就有了如下代码
db.personHealthCode.find({_id:NumberLong('39529165183456143')});
db.personHealthCode.find({_id:NumberLong('1234352405546668032')});
果然。。数据就这么轻轻松松的查了出来。。。。。。。。
PS:最后推测一下原因,因为长ID超过了19位,而对于这么长的数字,mongo认为自己很智能的运算会把他自认为是numberlong类型,这样即使不加numberlong的强制转换,也可以查询出来,而对于比较短的id,再进行find操作的时候,mongo会认为他是Number,那么是无法查询出来本身是Numberlong的类型的。
还有一个要说明的就是,列字段的数据类型,是根据列内最长的字段来决定的。。。