>首页  >数据库开发  >查看内容

谈MongoDB Shell下的长整型截断问题

2016/10/12 16:19:26|发布者: 艾悠乐|查看: 913|评论:0

MongoDB Shell下的长整型问题,是MongoDB臭名昭著的缺点。在这短暂的阅读中,Gian Maria Ricci(Linked in)将解释他是如何解决这一问题的。

在Mongo shell中简单的代码:

db.TestCollection.insert({"_id" : 1, "Value" : NumberLong(636002954392732556) })
db.TestCollection.find()

你想要在Mongo中插入一条记录,然后返回记录。记录被插入后返回值会令人大吃一惊。下面是从RoboMongo得到的输出:

{
 "_id" : 1.0,
 "Value" : NumberLong(636002954392732544) }

属性“值”没有你插入的数字,数字似乎是舍入和一些精度的丢失,即使它是一个NumberLong型和一个完全有效的64位长整型636002954392732556。这种行为让我很吃惊,因为我希望舍入的只有double型,而不是一个Int64的长整型。

实际上,使用64位的双精度浮点数表示,不能拥有一个64位长整型相同的精度,因为64位的一部分用来存储一个指数。如果你试图用双精度浮点来表示一个像636002954392732556一大串数字,那么一些四舍五入将会发生。如果你不相信,试试这个在线转换器转换636002954392732556,这里是结果:

图片描述

图1:浮点数舍入

上面就是舍入带来的问题,因为有些数字转换为浮点数格式,即使我使用NumberLong bson扩展指定,我想要一个长整型而不是一个浮点类型。

这背后的原因很微妙,接着试另一个例子,在Mongo shell(RoboMongo环境)中只输入NumberLong型(636002954392732556),并验证结果。

图片描述

图2:NumberLong直接从shell中获取舍入

这揭示了一个错误,在数返回时,则用引号括起来了,这说明引用是有问题的。在JavaScript中,每一个数字都是double型,如果你写NumberLong型(636002954392732556)JavaScript 转化这个作为参数传递的数字 636002954392732556来调用NumberLong函数。由于在JavaScript中的每个数字是一个double型,636002954392732556这个数会舍入之前它传递给NumberLong函数。

如果你周围有引用的数字,在这种情况下,将一个字符串传递给NumberLong型,舍入并不会发生,以及NumberLong函数是完全有能力将字符串转换为一个数字。

在Mongo shell中,当你使用NumberLong型创建数字总是使用引号,实际上,这个错误只发生在非常大的数字中,但是你需要明白如果创建一个脚本,那么就需要使用NumberLong型。

最新评论

热门资讯

排行榜