我已经在节点上使用pg-promise为Postgres获得了API,这很有效但我正在思考如何修改PUT语句以更好地处理输入中的NULLS。
以下是PUT语句的代码:
[Key]
public Guid AccountGuid { get; set; }
现在这个语句有效,但如果我将NULLS传递给下一次更新,它也会删除现有值。例如,如果我只想更新string1和date2,我必须发送整个json对象,或者所有其他值都设置为NULL。
有没有更好的方法来解决这个问题?我应该使用PATCH动词吗?
答案 0 :(得分:2)
我是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
查询,但它不会优雅;)
<强>更新强>
请注意,init
和skip
参数化的方式在图书馆的5.4.0版中已更改,请参阅the release notes。
从版本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
,当指定时表示方法返回的值,而不是抛出Cannot generate an UPDATE without any columns
。有关详细信息,请参阅helpers.update。
另请参阅:ColumnConfig。
答案 1 :(得分:1)
替代解决方案:
function updateFoo(req, res){
let {name, email, password} = req.body;
// Ex: req.body = { name: 'foo', password: 'bar' }
let data = { name, email, password }; // {name: 'foo', email:undefined, password:'bar}
//Remove ONLY undefined keys from data
Object.keys(data).forEach( key => { if(data[key] === undefined) delete data[key] });
let query = 'UPDATE foo SET';
let i = 1;
Object.keys(data).forEach( key => { query += ` ${key}=$${index},`; i++; })
query = query.slice(0, -1) // Remove exceeding comma
query += ` WHERE id=$${i}`;
let values = Object.values(data); // ['foo', 'bar']
values.push(req.params.id);
// .....
// query = 'UPDATE foo SET name=$1, password=$2 WHERE id=$3'
// values = ['foo', 'bar', req.params.id]
答案 2 :(得分:0)
谢谢@ vitaly-t!更快更清洁,总是很好的结果:)
作为参考,我还包括使用如上所述的帮助者的插入语句。
//firstly create a function that skips the nulls for strings
function str(column) {
return {
name: column,
skip: c => c.value === null || c.value === undefined || !c.exists
};
}
//now a function that skips nulls for integers, while parsing type
function int(column) {
return {
name: column,
skip: c => c.value === null || c.value === undefined || !c.exists,
init: c => +c.value
};
}
//creating a column set for all updates
var usefulColumSet = 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'), int('currency1'), int('currency2')
], {table: 'generic1'});
//*********************CREATE a single record*************************
function createRecord(req, res, next) {
var insert = pgp.helpers.insert(req.body, usefulColumSet);
db.none(insert)
.then(function(){
res.status(200)
.json({
status: 'success',
message: 'Inserted one record successully'
});
})
.catch(function(err){
return next(err);
});
}
//************************UPDATE a single record*************
function updateRecord(req, res, next) {
var update = pgp.helpers.update(req.body, usefulColumSet) + ' WHERE id = ' + parseInt(req.params.id);
db.none(update)
.then(function() {
res.status(200)
.json({
status: 200,
message: 'updated a single record cleanly'
});
})
.catch(function(err) {
return next(err);
});
}