2016-03-03 137 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