pg-promise 为 select 查询创建自定义过滤器
pg-promise create custom filters for select query
我正在处理的功能是获取一个输入对象,该对象具有 7 个不同的键值,并且每个键值都可以是未定义的,也可以是未定义的。我想根据输入中存在的那些键值来过滤我的数据库。例如,如果只有 input.userID
存在,我想 运行 这个查询:
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});
我所做的是创建了一个参数和键对象,如下所示:
if(input.userID) {
keys.push('userID');
params.push(input.userID);
query = addFilterToTheQuery(query, 'userID', input.userID, filteredItemsCount);
filteredItemsCount = filteredItemsCount +1;
}
addFilterToTheQuery
是我自己实现的一个简单函数。我基本上做了 7 个 if 案例。然后我必须使用这些键和参数值以可能需要另一个巨大的 switch case 代码的方式传递给查询函数。
这是唯一的方法吗?有没有更好的方法来消除这段代码中的冗余?
例如,如果我们想转换一个具有属性-过滤器值的对象,我们可以这样做:
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; // property renamed later - see UPDATE below
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);
};
}
测试
var filter = new FilterSet({
first: 1,
second: 'two'
});
var test = pgp.as.format('WHERE ', filter);
console.log(test);
这输出:
WHERE "first" = 1 AND "second" = 'two'
如果您的过滤器要用作 %value%
和 LIKE
或 ILIKE
,那么您需要相应地更改您的自定义类型。
更新
下面是为最新 pg-promise(版本 8.x 或更高版本)重写的相同示例:
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);
}
}
我正在处理的功能是获取一个输入对象,该对象具有 7 个不同的键值,并且每个键值都可以是未定义的,也可以是未定义的。我想根据输入中存在的那些键值来过滤我的数据库。例如,如果只有 input.userID
存在,我想 运行 这个查询:
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});
我所做的是创建了一个参数和键对象,如下所示:
if(input.userID) {
keys.push('userID');
params.push(input.userID);
query = addFilterToTheQuery(query, 'userID', input.userID, filteredItemsCount);
filteredItemsCount = filteredItemsCount +1;
}
addFilterToTheQuery
是我自己实现的一个简单函数。我基本上做了 7 个 if 案例。然后我必须使用这些键和参数值以可能需要另一个巨大的 switch case 代码的方式传递给查询函数。
这是唯一的方法吗?有没有更好的方法来消除这段代码中的冗余?
例如,如果我们想转换一个具有属性-过滤器值的对象,我们可以这样做:
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; // property renamed later - see UPDATE below
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);
};
}
测试
var filter = new FilterSet({
first: 1,
second: 'two'
});
var test = pgp.as.format('WHERE ', filter);
console.log(test);
这输出:
WHERE "first" = 1 AND "second" = 'two'
如果您的过滤器要用作 %value%
和 LIKE
或 ILIKE
,那么您需要相应地更改您的自定义类型。
更新
下面是为最新 pg-promise(版本 8.x 或更高版本)重写的相同示例:
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);
}
}