我在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动词吗?
我是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查询,尽管它不会那么优雅;)
UPDATE
更新
请注意,在库的版本5.4.0中,方式init和skip参数化已更改,请参见发行说明。
init
skip
从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。
emptyUpdate
Cannot generate an UPDATE without any columns
另请参见:ColumnConfig。