3

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

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

4

1 回答 1

5

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

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

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%LIKEor一起使用ILIKE,那么您需要相应地更改您的自定义类型。

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

请参阅自定义类型格式

于 2016-03-03T20:06:45.407 回答