2016-11-19 43 views
1

我已經有了一個使用pg-promise作爲Postgres的節點上的API,這很好,但是我在考慮如何修改PUT語句來處理輸入中的NULLS好一點。跳過pg-promise的更新列

以下是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動詞嗎?

回答

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查詢相應地,儘管它不會那麼優雅;)

UPDATE

請注意和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 

UPDATE

庫的版本5.6.7接收到該進一步的改進 - 選項emptyUpdate,它指定當代表值,以通過該方法返回,而不是拋Cannot generate an UPDATE without any columns。詳情請參閱helpers.update

另請參閱:ColumnConfig

+1

太棒了!感謝維塔利:) –

+0

@ adam.sellers查看有關最新版本的更新;) –

+0

@adam。賣家另一個更新已被添加 - 選項'emptyUpdate';) –

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); 
     }); 
} 
+0

因爲你沒有提供屬性'def' - 默認值,當屬性不存在時,你將最終與'c.value'等於'undefined'在那些的情況下,所以不需要檢查'!c.exists';) –