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

Ant*_*ine 16 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
    });
Run Code Online (Sandbox Code Playgroud)

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

[{id_brand: "180", brand: "Ford"}, {id_brand: "120", brand: "Nike"}]
Run Code Online (Sandbox Code Playgroud)

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

vit*_*y-t 28

这确实是标准行为.

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

原因是64位整数在JavaScript中没有精确的本机表示,它只能以一定的精度呈现64位数字,并且不适合表示全部64位数字.

另请参见:如何在Node.js中执行64位整数运算?


这个问题有三种可能的解决方案......

解决方案1

不要使用64位整数来存储Id-s,如果您的表预计不会有超过40亿条记录,请使用默认number类型,即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
    });
Run Code Online (Sandbox Code Playgroud)

请参见Database.each.

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

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

请参见Database.one.

解决方案3

您可以使底层node-postgres驱动程序忽略转换安全性,并将这些类型转换为整数.我不能说一般来说这是一个好主意,只能通过bigint(参见pg-types)轻松完成:

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

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

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


Moh*_*lal 13

@vitaly-t 答案解释了一切!

\n

对于 @vitaly-t 答案的 postgree (解决方案 3)上的隐式全局转换。

\n

这里是你需要了解的:

\n
const typesBuiltins = {\n    BOOL: 16,\n    BYTEA: 17,\n    CHAR: 18,\n    INT8: 20,\n    INT2: 21,\n    INT4: 23,\n    REGPROC: 24,\n    TEXT: 25,\n    OID: 26,\n    TID: 27,\n    XID: 28,\n    CID: 29,\n    JSON: 114,\n    XML: 142,\n    PG_NODE_TREE: 194,\n    SMGR: 210,\n    PATH: 602,\n    POLYGON: 604,\n    CIDR: 650,\n    FLOAT4: 700,\n    FLOAT8: 701,\n    ABSTIME: 702,\n    RELTIME: 703,\n    TINTERVAL: 704,\n    CIRCLE: 718,\n    MACADDR8: 774,\n    MONEY: 790,\n    MACADDR: 829,\n    INET: 869,\n    ACLITEM: 1033,\n    BPCHAR: 1042,\n    VARCHAR: 1043,\n    DATE: 1082,\n    TIME: 1083,\n    TIMESTAMP: 1114,\n    TIMESTAMPTZ: 1184,\n    INTERVAL: 1186,\n    TIMETZ: 1266,\n    BIT: 1560,\n    VARBIT: 1562,\n    NUMERIC: 1700,\n    REFCURSOR: 1790,\n    REGPROCEDURE: 2202,\n    REGOPER: 2203,\n    REGOPERATOR: 2204,\n    REGCLASS: 2205,\n    REGTYPE: 2206,\n    UUID: 2950,\n    TXID_SNAPSHOT: 2970,\n    PG_LSN: 3220,\n    PG_NDISTINCT: 3361,\n    PG_DEPENDENCIES: 3402,\n    TSVECTOR: 3614,\n    TSQUERY: 3615,\n    GTSVECTOR: 3642,\n    REGCONFIG: 3734,\n    REGDICTIONARY: 3769,\n    JSONB: 3802,\n    REGNAMESPACE: 4089,\n    REGROLE: 4096\n};\n
Run Code Online (Sandbox Code Playgroud)\n

您可以在这里找到
\n https://github.com/brianc/node-pg-types/blob/master/lib/builtins.js

\n

一般情况下可以这样访问

\n
const pg = require(\'pg\');\n\npg.types.setTypeParser(pg.types.builtins.INT8, (value: string) => {\n   return parseInt(value);\n});\n\npg.types.setTypeParser(pg.types.builtins.FLOAT8, (value: string) => {\n    return parseFloat(value);\n});\n\npg.types.setTypeParser(pg.types.builtins.NUMERIC, (value: string) => {\n    return parseFloat(value);\n});\n
Run Code Online (Sandbox Code Playgroud)\n

通常会处理所有数字数据。

\n

如果由于某种原因 pg.types.builtins 无法访问(在我的情况下,由于某种原因在打字稿中)。你直接复制过去就可以了。或者直接使用对应的映射号码。

\n

更新(以避免混淆)

\n

截至目前 "pg": "^7.11.0"。\npg 使用的是 pg-types 2.0.1,它根本不包含内置函数。\n之前的所有版本也是如此。\n这导致访问pg.types.builtins.被不可行(在上述版本之前的任何版本中)。

\n

我之前提到的解决方案是复制映射就像我在当前项目中所做的那样。(检查上面所有的片段以复制它)\n在此输入图像描述\n在此输入图像描述

\n

或者直接使用给定列表的相应映射。

\n
pgp.pg.types.setTypeParser(20, parseInt);\n
Run Code Online (Sandbox Code Playgroud)\n

另一种解决方法是直接使用 pg-types 包。在它的最新版本中。

\n
const types = require(\'pg-types\');\n// types.builtins.INT8\n
Run Code Online (Sandbox Code Playgroud)\n

否则,PR 由 @vitaly-t 填写,可以在下面的链接中看到:
\n https://github.com/brianc/node-postgres/pull/1937/commits/c7666214833715ac2494b81865cfe1ea7cef9289

\n

pg-types更新withing包 (node-postgres)的版本pg。\n在此输入图像描述

\n

所以一旦被接受。首字母缩写示例将开始工作。

\n

请注意,我的来源最初是官方自述文件pg-types
\n https://github.com/brianc/node-pg-types

\n

在此输入图像描述

\n

\xc2\xa0另一个也是最后一个注释:

\n

这涉及到typescript的使用。

\n

pg-types与当前版本一样,打字稿打字不包括内置命令"pg-types": "^2.1.0"。该更新了。所以你要么自己添加打字。

\n
typeof types & {builtins: {[key in builtinsTypes]: number}}\n
Run Code Online (Sandbox Code Playgroud)\n

其中builtinsTypes 是所有属性名称的并集。

\n

(但是我发现复制粘贴孔对象更快、更短、更干净)。

\n

您可以使用枚举来做到这一点,如下所示

\n
enum TypeId {\n        BOOL = 16,\n        BYTEA = 17,\n        CHAR = 18,\n        INT8 = 20,\n        INT2 = 21,\n        INT4 = 23,\n        REGPROC = 24,\n        TEXT = 25,\n        OID = 26,\n        TID = 27,\n        XID = 28,\n        CID = 29,\n        JSON = 114,\n        XML = 142,\n        PG_NODE_TREE = 194,\n        SMGR = 210,\n        PATH = 602,\n        POLYGON = 604,\n        CIDR = 650,\n        FLOAT4 = 700,\n        FLOAT8 = 701,\n        ABSTIME = 702,\n        RELTIME = 703,\n        TINTERVAL = 704,\n        CIRCLE = 718,\n        MACADDR8 = 774,\n        MONEY = 790,\n        MACADDR = 829,\n        INET = 869,\n        ACLITEM = 1033,\n        BPCHAR = 1042,\n        VARCHAR = 1043,\n        DATE = 1082,\n        TIME = 1083,\n        TIMESTAMP = 1114,\n        TIMESTAMPTZ = 1184,\n        INTERVAL = 1186,\n        TIMETZ = 1266,\n        BIT = 1560,\n        VARBIT = 1562,\n        NUMERIC = 1700,\n        REFCURSOR = 1790,\n        REGPROCEDURE = 2202,\n        REGOPER = 2203,\n        REGOPERATOR = 2204,\n        REGCLASS = 2205,\n        REGTYPE = 2206,\n        UUID = 2950,\n        TXID_SNAPSHOT = 2970,\n        PG_LSN = 3220,\n        PG_NDISTINCT = 3361,\n        PG_DEPENDENCIES = 3402,\n        TSVECTOR = 3614,\n        TSQUERY = 3615,\n        GTSVECTOR = 3642,\n        REGCONFIG = 3734,\n        REGDICTIONARY = 3769,\n        JSONB = 3802,\n        REGNAMESPACE = 4089,\n        REGROLE = 4096\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如在pg-promise\n https://github.com/vitaly-t/pg-promise/blob/v9/typescript/pg-subset.d.ts#L103中完成的

\n

一旦一切更新。使用 pg 是正确的选择。

\n

更新

\n

包已更新。并且您可以按预期使用它。

\n
const typesBuiltins = {\n    BOOL: 16,\n    BYTEA: 17,\n    CHAR: 18,\n    INT8: 20,\n    INT2: 21,\n    INT4: 23,\n    REGPROC: 24,\n    TEXT: 25,\n    OID: 26,\n    TID: 27,\n    XID: 28,\n    CID: 29,\n    JSON: 114,\n    XML: 142,\n    PG_NODE_TREE: 194,\n    SMGR: 210,\n    PATH: 602,\n    POLYGON: 604,\n    CIDR: 650,\n    FLOAT4: 700,\n    FLOAT8: 701,\n    ABSTIME: 702,\n    RELTIME: 703,\n    TINTERVAL: 704,\n    CIRCLE: 718,\n    MACADDR8: 774,\n    MONEY: 790,\n    MACADDR: 829,\n    INET: 869,\n    ACLITEM: 1033,\n    BPCHAR: 1042,\n    VARCHAR: 1043,\n    DATE: 1082,\n    TIME: 1083,\n    TIMESTAMP: 1114,\n    TIMESTAMPTZ: 1184,\n    INTERVAL: 1186,\n    TIMETZ: 1266,\n    BIT: 1560,\n    VARBIT: 1562,\n    NUMERIC: 1700,\n    REFCURSOR: 1790,\n    REGPROCEDURE: 2202,\n    REGOPER: 2203,\n    REGOPERATOR: 2204,\n    REGCLASS: 2205,\n    REGTYPE: 2206,\n    UUID: 2950,\n    TXID_SNAPSHOT: 2970,\n    PG_LSN: 3220,\n    PG_NDISTINCT: 3361,\n    PG_DEPENDENCIES: 3402,\n    TSVECTOR: 3614,\n    TSQUERY: 3615,\n    GTSVECTOR: 3642,\n    REGCONFIG: 3734,\n    REGDICTIONARY: 3769,\n    JSONB: 3802,\n    REGNAMESPACE: 4089,\n    REGROLE: 4096\n};\n
Run Code Online (Sandbox Code Playgroud)\n

另请检查上述vitaly-t答案的UPDATE-2部分\n /sf/answers/2742366931/

\n