如何使用nodejs pg-promise库向pg表中插入一个带有uuid数组的记录?[英] how to insert a record with a uuid array into a pg table using nodejs pg-promise library

本文是小编为大家收集整理的关于如何使用nodejs pg-promise库向pg表中插入一个带有uuid数组的记录?的处理方法,想解了如何使用nodejs pg-promise库向pg表中插入一个带有uuid数组的记录?的问题怎么解决?如何使用nodejs pg-promise库向pg表中插入一个带有uuid数组的记录?问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我需要在DB中有一个表,该表包含一个列,该列是UUID对象的数组(UUID [] type)

但是,当我尝试使用名为pg-promise的nodejs库插入其中时,它会失败

我收到以下错误消息,告诉我我需要重写演员表或表达式

{"name":"error","length":206,"severity":"ERROR","code":"42804","hint":"You will need to rewrite or cast the expression.","position":"230","file":"src\\backend\\parse
r\\parse_target.c","line":"510","routine":"transformAssignedExpr"}

这很奇怪 由于当我尝试在同一精确表上输入单个uuid时,我绝对没有问题(这意味着,我没有代表uuid的问题,顺便说一句,我将它们创建为来自另一个lib的文本变量,但它们是普通的旧文本变量)

尝试将文本对象输入到同一列中时,我也没有问题(如果我更改表格为具有文本[]列而不是uuid []列)

这是我的代码

////////////////

var Promise = require('bluebird');
var pgpLib = require('pg-promise');
var pgp = pgpLib();
var cn = confUtil.pgDbConnectionConfiguration();
var db = pgp(cn);

//////////////////

var newEntity={};
newEntity.hash      = uuid.v4();    
newEntity.location  = {X:2394876,Y:2342342};
newEntity.mother    = uuid.v4();
newEntity.timestamp = Date.now();
newEntity.content   = {content:"blah"};
newEntity.sobList   = [uuid.v4(),uuid.v4(),uuid.v4()];
addEntity (newEntity);

////////////////////

function addEntity(newEntity) {
    var insertEntityQueryPrefix='insert into entities (';
    var insertEntityQueryMiddle=') values (';
    var insertEntityQueryPostfix="";
    var insertEntityQuery="";

    Object.keys(newEntity).forEach(function(key){
        insertEntityQueryPrefix=insertEntityQueryPrefix+'"'+key+'",';
        insertEntityQueryPostfix=insertEntityQueryPostfix+'${'+key+'},';
    });
    insertEntityQueryPrefix=insertEntityQueryPrefix.slice(0,-1);
    insertEntityQueryPostfix=insertEntityQueryPostfix.slice(0,-1)+")";  
    insertEntityQuery=insertEntityQueryPrefix+insertEntityQueryMiddle+insertEntityQueryPostfix;

    //longStoryShort  this is how the query template i used looked like
    /*
        "insert into entities ("hash","location","mother","timestamp","content","sobList") values (${hash},${location},${mother},${timestamp},${content},${sobList})"
    */
    //and this is the parameters object i fed to the query i ran it when it failed
    /*
        {
            "hash": "912f6d85-8b47-4d44-98a2-0bbef3727bbd",
            "location": {
                "X": 2394876,
                "Y": 2342342
            },
            "mother": "87312241-3781-4d7c-bf0b-2159fb6f7f74",
            "timestamp": 1440760511354,
            "content": {
                "content": "bla"
            },
            "sobList": [
                "6f2417e1-b2a0-4e21-8f1d-31e64dea6358",
                "417ade4b-d438-4565-abd3-a546713be194",
                "e4681d92-0c67-4bdf-973f-2c6a900a5fe4"
            ]
        }
    */

    return db.tx(function () {
        var processedInsertEntityQuery = this.any(insertEntityQuery,newEntity);
        return Promise.all([processedInsertEntityQuery])
    })
    .then(
        function (data) {
            return newEntity;
        }, 
        function (reason) {
            throw new Error(reason);
        });
}

推荐答案

插入uuid-s的数组是一种特殊情况,需要显式类型的铸造,因为您将uuid-s传递到类型uuid[]作为文本字符串数组中.

您需要更改INSERT查询:用${sobList}::uuid[]替换${sobList}.这将指示postgesql将字符串数组转换为uuid-s的数组.

与您的问题无关,在执行单个请求时,您不需要在db.tx内使用Promise.all.您可以简单地从插入请求返回结果:

return this.none(insertEntityQuery,newEntity);

尽管使用交易执行单个请求同样毫无意义:)

更新

最新版本的 pg-promise 支持自定义类型格式,因此您可以为查询格式编写自己的自定义类型,避免使用explicit类型铸造.

对于您在数组中使用UUID-S的示例,您可以实现自己的UUID类型:

const UUID = a => ({rawType = true, toPostgres = () => a.v4()});

对于任何uuidValue在数组或单独的uuidValue中,您可以使用UUID(uuidValue)进行自动格式.

本文地址:https://www.itbaoku.cn/post/1763862.html