【问题标题】:pg-promise create custom filters for select querypg-promise 为选择查询创建自定义过滤器
【发布时间】:2016-06-17 05:16:17
【问题描述】:

我正在处理的函数是获取一个具有 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 代码的方式传递给查询函数。

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

【问题讨论】:

  • 1.像%value% 这样的语法只能用于LIKE 2。您不能将params[1] 作为第三个参数传递给方法query - see it in the API

标签: javascript node.js postgresql pg-promise


【解决方案1】:

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; // 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'

如果您的过滤器将用作%value%LIKEILIKE,那么您需要相应地更改您的自定义类型。

查看相关问题: 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);
    }
}

Custom Type Formatting

【讨论】:

  • 我编辑了这个问题。我是否正确理解了您提到的编辑?
  • 现在看起来不错。我添加了相关问题的链接,以帮助您在需要时扭曲输出;)
猜你喜欢
  • 2019-04-04
  • 1970-01-01
  • 2015-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 2015-08-19
相关资源
最近更新 更多