【问题标题】:MongoDB/Mongoose saves and gets wrong integerMongoDB/Mongoose 保存并获取错误的整数
【发布时间】:2018-07-29 14:29:55
【问题描述】:

我遇到了一个非常奇怪的 mongoose 错误 - 每次我尝试保存大量数字(在本例中为 76561198063200687)时,mongoose 或 mongodb 都会错误地保存整数。

例如,当我调用SomeModel.findOneAndUpdate({name: "Pietrov"}, {userid: 7656119806320068**7**}) 时,字段userid 正在更新为76561198063200688

更奇怪的是,当我 now (SomeModel.findOne({name: "Pietrov"})) 为同一个文档调用 findOne 时,用户 ID 为 76561198063200690 - 差了两个(已经错了) , 一个单独的用户 ID)。

有人可以帮我解决这个奇怪的问题吗?

我使用的是 mongoose 5.2,尽管我在早期版本 (5.x) 中体验到了相同的效果。

【问题讨论】:

  • 您能否提供更多信息...例如您可能已配置的 mongoose/mongoDB 架构/钩子等?
  • 请注意您关闭this question 的原因,因为我们可以在那里进一步讨论。所有多用户数据库都具有可用于防止竞争条件的功能。例如,如果你想为一个不存在的 id 添加一条记录,这是一个特定的操作,数据库将能够在一次数据库调用中自动执行。我不知道您的具体数据库,因此您必须对该主题进行一些研究。
  • 而且,集群的情况更糟,因为这为竞争条件创造了更多机会(更多的服务器都在竞争修改同一个数据库)。
  • 对不起,我已经取消删除帖子了!随时在那里再次发布您的 cmets。也很重要。我正在使用 postgres,但还没有找到一种方法可以在单个查询中完全满足我的要求。我很想(错误地)为此使用交易,但担心这是一种糟糕的方式来做我想做的事情。

标签: node.js mongodb mongoose


【解决方案1】:

此问题与 mongodb 或 mongoose 无关。这种看似奇怪的行为是因为您的号码不是安全整数

Number.MAX_SAFE_INTEGER < 76561198063200688 // true
Number.isSafeInteger(76561198063200688)     // false

JavaScript 中的所有数字都是双精度浮点格式的数字。这个数字可以安全地表示-(2**53 - 1)2**53 - 1 之间的整数。这意味着如果您使用超出该范围的整数,它们可以四舍五入以适合 IEEE-754 表示。更多信息请查看isSafeInteger documentation on MDN

JavaScript 现在有一种新的任意精度整数类型,称为BigInt。但它们仅在节点 starting from version 10.4 中受支持。据我了解,猫鼬默认情况下不适用于大整数,因此您可能需要为它们创建一个custom schema type。否则,将此 id 存储为字符串,因为您可能不需要对它们执行任何计算。

【讨论】:

  • 太棒了,非常感谢!您认为将这些数字存储在字符串中会是“糟糕的数据库设计”吗?毕竟,您应该将整数存储为整数 - 至少从我所听到的情况来看
  • 这真的取决于这个字段代表什么。如果它仅用作唯一标识符,那么我认为没关系。我能想到的唯一缺点是字符串表示会占用更多空间。另一方面,如果您需要对它们进行递增、数值比较或从某个值范围内查询记录,那么使用字符串将是一个非常糟糕的主意。
  • 如果您必须进行计算,然后在更新数据库之前再次将其转换回String,则仍然可以在查询期间将字符串数字转换为 BigInt 或类似的东西。
猜你喜欢
  • 1970-01-01
  • 2015-06-11
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 2017-07-27
  • 2016-11-22
  • 2011-07-01
相关资源
最近更新 更多