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

pg-promise create custom filters for select query

本文关键字:自定义 过滤器 创建 查询 选择 PG-promise      更新时间:2023-09-26

我正在处理的函数是获取一个具有 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 个。然后,我必须使用这些键和参数值以可能需要另一个巨大开关大小写代码的方式传递给查询函数。

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

自定义类型格式在这里最合适。

例如,如果我们想转换一个具有属性 - filter 值的对象,我们可以这样做:

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 $1', filter);
console.log(test);

这输出:

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

如果要将筛选器用作与 LIKEILIKE%value%,则需要相应地更改自定义类型。

请参阅相关问题:42, 49, 89, 90,

更新

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

请参阅自定义类型格式设置。