pg-promise为选择查询创建自定义过滤器

时间:2016-03-03 18:02:33

标签: javascript node.js postgresql pg-promise

我正在处理的函数是获取一个具有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});

我所做的是我创建了一个这样的params和keys对象:

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

addFilterToTheQuery是我自己实现的一个简单函数。如果情况我基本上做7。然后我必须使用这些键和参数值以一种可能需要另一个巨大的开关案例代码的方式传递给查询函数。

这是唯一的方法吗?有没有更好的方法来摆脱这段代码中的冗余?

1 个答案:

答案 0 :(得分:3)

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

更新

以下是为最新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);
    }
}

请参阅Custom Type Formatting