一尘不染

使用pg-promise跳过更新列

node.js

我在Postgres上使用pg-promise的节点上建立了一个API,效果很好,但是我正在考虑如何修改PUT语句以更好地处理输入中的NULLS。

以下是PUT语句的代码:

    //UPDATE a single record
function updateRecord(req, res, next) {
    db.none('update generic1 SET string1=$1,' +
                               'string2=$2,' +
                               'string3=$3,' +
                               'string4=$4,' +
                               'string5=$5,' +
                               'string6=$6,' +
                               'integer1=$7,' +
                               'integer2=$8,' +
                               'integer3=$9,' +
                               'date1=$10,' +
                               'date2=$11,' +
                               'date3=$12,' +
                               'currency1=$13,' +
                               'currency2=$14' +
            'WHERE id = $15',
            [req.body.string1,
             req.body.string2,
             req.body.string3,
             req.body.string4,
             req.body.string5,
             req.body.string6,
             parseInt(req.body.integer1),
             parseInt(req.body.integer2),
             parseInt(req.body.integer3),
             req.body.date1,
             req.body.date2,
             req.body.date3,
             parseInt(req.body.currency1),
             parseInt(req.body.currency2),
             parseInt(req.params.id)])
        .then(function(){
            res.status(200)
                .json({
                    'status': 'success',
                    'message': 'updated one record'
                });
        })
        .catch(function(err){
            return next(err);
        });
}

现在,此语句有效,但是如果我将NULLS传递给下一个更新,它也会删除现有值。例如,如果我只想更新string1和date2,则必须发送整个json对象,否则所有其他值都将设置为NULL。

有没有更好的方法来解决这个问题?我应该改用PATCH动词吗?


阅读 218

收藏
2020-07-07

共1个答案

一尘不染

我是pg-promise的作者;)

var pgp = require('pg-promise')({
    capSQL: true // capitalize all generated SQL
});

// generic way to skip NULL/undefined values for strings:
function str(col) {
    return {
        name: col,
        skip: function () {
            var val = this[col];
            return val === null || val === undefined;
        }
    };
}

// generic way to skip NULL/undefined values for integers,
// while parsing the type correctly:
function int(col) {
    return {
        name: col,
        skip: function () {
            var val = this[col];
            return val === null || val === undefined;
        },
        init: function () {
            return parseInt(this[col]);
        }
    };
}

// Creating a reusable ColumnSet for all updates:
var csGeneric = new pgp.helpers.ColumnSet([
    str('string1'), str('string2'), str('string3'), str('string4'), str('string5'),
    str('string6'), int('integer1'), int('integer2'), int('integer3'),
    str('date1'), str('date2'), str('date3')
], {table: 'generic1'});

// Your new request handler:
function updateRecord(req, res, next) {

    var update = pgp.helpers.update(req.body, csGeneric) + ' WHERE id = ' +
        parseInt(req.params.id);

    db.none(update)
        .then(function () {
            res.status(200)
                .json({
                    'status': 'success',
                    'message': 'updated one record'
                });
        })
        .catch(function (err) {
            return next(err);
        });
}

参见helpers名称空间;)


另外,您可以对每列进行自己的验证,然后相应地生成UPDATE查询,尽管它不会那么优雅;)

更新

请注意,在库的版本5.4.0中,方式initskip参数化已更改,请参见发行说明

从5.4.0版开始,您可以简化代码,如下所示:

// generic way to skip NULL/undefined values for strings:
function str(column) {
    return {
        name: column,
        skip: c => c.value === null || c.value === undefined
    };
}

// generic way to skip NULL/undefined values for integers,
// while parsing the type correctly:
function int(column) {
    return {
        name: column,
        skip: c => c.value === null || c.value === undefined,
        init: c => +c.value
    };
}

而且,如果您要跳过根本没有传入的属性,因此甚至不存在于对象中,请使用以下方法:

skip: c => c.value === null || c.value === undefined

你可以这样做:

skip: c => !c.exists

更新

库的5.6.7版本对此选项进行了进一步改进emptyUpdate,当指定此选项时,该选项表示方法要返回的值,而不是throwing Cannot generate an UPDATE without any columns。有关详细信息,请参见helpers.update

另请参见:ColumnConfig

2020-07-07