node.js - pg-promise 将整数作为字符串返回

标签 node.js pg-promise

我对包含 bigint 类型列的表进行了这个简单的查询。

但是,当我查询它时,pg-promise将此列的值作为字符串返回。我在文档中找不到有关此的信息。这是标准行为吗?

var ids = [180, 120];

db.any('SELECT id_brand, brand from catalog_brand WHERE id_brand in ($1:csv)', [ids])
    .then((data) => {
        // return results
    });

data 采用以下形式,id 为 string 而不是 int:

[{id_brand: "180", brand: "Ford"}, {id_brand: "120", brand: "Nike"}]

有什么可以指教的pg-promise返回实际类型?

最佳答案

下面有很多历史积累。但是如果你使用的是 Node.js v10.4.0 或更高版本,你可以跳过所有这些,并跳转到底部的 UPDATE-2 部分。


这确实是标准行为。

bigint 是 64 位的,所有 64 位整数都由底层 node-postgres 返回驱动程序类型为 string,而 32 位驱动程序返回为 number

原因是 64 位整数在 JavaScript 中没有准确的原生表示,只能以一定精度表示 64 位数字,不适合表示 64 位的全范围数字。

另请参阅:How to do 64bit Integer arithmetic in Node.js?


这个问题有三种可能的解决方案,选择最适合你的一个:

解决方案 1

不要使用 64 位整数来存储 Id-s,如果您的表预计不会超过 40 亿条记录,请改用默认的 int 类型,即 32-位,并将自动返回为整数。

解决方案 2

即时将返回的 id-s 转换为整数,但请记住,一旦您的 id-s 达到足够高的数字(53 位),转换后的值就会失真/改变。

但是,您可以使用可以将字符串正确转换为 64 位整数的专用库(请参阅上面的链接),但这可能很难跨查询使用。


即时转换您的 id-s 的示例:

db.each('SELECT id_brand FROM catalog_brand WHERE id_brand in ($1:csv)', [ids], cat=> {
    cat.id_brand = parseInt(cat.id_brand)
})
    .then(rows => {
        // id_brand is now an integer in each row
    });

Database.each .

作为另一个例子,记录计数总是以 bigint 的形式返回,因此获得这些计数的最佳方法是通过内联值转换 + 转换,如下所示:

db.one('SELECT count(*) FROM catalog_brand', [], c => +c.count)
    .then(count => {
        // count = a proper integer value, rather than an object with a string
    });

Database.one .

解决方案 3

您可以将基础 node-postgres驱动程序无视转换安全性并将此类类型转换为各处的整数。我不能说这是否是一个好主意,只是可以通过 pgp.pg.types.setTypeParser(...) 轻松完成(参见 pg-types ):

// Convert bigserial + bigint (both with typeId = 20) to integer:
pgp.pg.types.setTypeParser(20, parseInt);

UPDATE-1

当通过 TypeScript 使用 pg-promise v9 或更高版本时,您可以将上面的代码替换为:

pgp.pg.types.setTypeParser(TypeId.INT8, parseInt);

请注意,解决方案 2 和 3 做同样的事情,但在两个不同的级别:

  • 解决方案 2 中的显式本地转换
  • 解决方案 3 中的隐式全局转换

UPDATE-2

Version 9.3.0的库添加了对原生 BigInt 的支持类型,现在可以使用,如果您运行的是 Node.js v10.4.0 或更高版本。

要让驱动程序自动使用 BigInt对于 BIGINT + BIGSERIAL:

pgp.pg.types.setTypeParser(20, BigInt); // Type Id 20 = BIGINT | BIGSERIAL

更多详情,见BigInt Manual在项目的维基中。

关于node.js - pg-promise 将整数作为字符串返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39168501/

相关文章:

javascript - pg-promise 在 UPDATE SET 语句中使用命名参数

pg-promise:BEGIN 和 COMMIT 何时发送?

javascript - 使用cheerio从ul中提取2个元素

node.js - 如何在一个 Express app.get() 中使用多个 res.render()

postgresql - 多个查询的批处理 INSERT 引发外键冲突

sql - 使用返回的 id 插入多对多关系表

javascript - Pg-promise 性能提升 : ON CONFLICT

node.js - 处理 Node.js spawnSync 错误

node.js - 如何从 Mongodb 集合中流式传输文档

javascript - Node js,如何在循环后运行代码同步