2016-03-03 111 views
2

我正在處理的函數獲取具有7個不同鍵值的輸入對象,並且它們中的每一個都可能是未定義的。我想根據輸入中存在的鍵值過濾數據庫。例如,如果只存在input.userID我想運行此查詢:pg-promise爲選擇查詢創建自定義過濾器

db.query("...WHERE userID = ${userID}", {userID: input.userID}); 

否則,如果input.userID和input.startTime都存在,我想這樣做:

db.query("...WHERE userID = ${userID} and startTime= ${startTime}", {userID: input.userID, startTime: input.startTime}); 

我所做的是我創建了一個PARAMS和鍵對象是這樣的:

if(input.userID) { 
    keys.push('userID'); 
    params.push(input.userID); 
    query = addFilterToTheQuery(query, 'userID', input.userID, filteredItemsCount); 
    filteredItemsCount = filteredItemsCount +1; 
} 

addFilterToTheQuery是一個簡單的功能,我實現了自己。如果情況基本上是7。然後,我必須使用這些鍵和參數值以可能需要另一個巨大的開關盒代碼的方式傳遞給查詢函數。

這是唯一的方法來做到這一點?有沒有更好的方法來擺脫這段代碼中的冗餘?

+0

1.語法like'%value%'只能用於'LIKE' 2.您不能將'params [1]'作爲第三個參數傳遞給'query' - [在API中查看]( http://vitaly-t.github.io/pg-promise/Database.html#.query)。 –

回答

2

Custom Type Formatting這裏最合適。

例如,如果我們想將對象轉換與特性 - 過濾器值,我們可以像這樣做:

var pgp = require('pg-promise')(/* initialization options */); 

function FilterSet(filters) { 
    if (!filters || typeof filters !== 'object') { 
     throw new TypeError('Parameter \'filters\' must be an object.'); 
    } 
    this._rawDBType = true; 
    this.formatDBType = function() { 
     var keys = Object.keys(filters); 
     var s = keys.map(function (k) { 
      return pgp.as.name(k) + ' = ${' + k + '}'; 
     }).join(' AND '); 
     return pgp.as.format(s, filters); 
    }; 
} 

TEST

var filter = new FilterSet({ 
    first: 1, 
    second: 'two' 
}); 

var test = pgp.as.format('WHERE $1', filter); 

console.log(test); 

此輸出:

WHERE "first" = 1 AND "second" = 'two' 

如果您的過濾器將被用作%value%LIKEILIKE,那麼您需要相應地更改自定義類型。

查看相關問題:

42498990

UPDATE

下面是同樣的例子最新pg-promise(6.5.0或更新版本)重新編寫

const pgp = require('pg-promise')(/* initialization options */); 

class FilterSet { 
    constructor(filters) { 
     if (!filters || typeof filters !== 'object') { 
      throw new TypeError('Parameter \'filters\' must be an object.'); 
     } 
     this.filters = filters; 
     this._rawType = true; // do not escape the result from toPostgres() 
    } 

    toPostgres(/*self*/) { 
     // self = this 
     const keys = Object.keys(this.filters); 
     const s = keys.map(k => pgp.as.name(k) + ' = ${' + k + '}').join(' AND '); 
     return pgp.as.format(s, this.filters); 
    } 
} 

參見Custom Type Formatting

+1

我編輯了這個問題。我瞭解你提到的編輯是否正確? – Andi

+0

現在看起來不錯。如果需要,我添加了相關問題的鏈接以幫助您扭轉輸出;) –

+0

非常感謝,這些真的有幫助:) – Andi