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

问题描述 投票:9回答:1

我对包含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 pg-promise
1个回答
22
投票

这确实是标准行为。

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的示例:

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);

请注意,解决方案2和3执行相同的操作,但是在两个不同的级别上:

  • 解决方案2中的显式本地转换
  • 解决方案3中的隐式全局转换
© www.soinside.com 2019 - 2024. All rights reserved.