Knex查询构建 - 动态构建链

时间:2016-05-13 03:54:01

标签: node.js knex.js

我为knex交换了node-DBI,因为它有更多我需要的功能。

到目前为止,我再次做出同样的选择,但只有一件事让我退缩:编写抽象方法,其中包含一个选项变量,其中params包含where,innerjoin等。

使用node-dbi我可以使用这些变量轻松伪造一个字符串,但我似乎无法创建knex链,因为在使用开关后,你会得到knex.method不是函数。

知道如何解决这个问题吗?

我正在寻找

中的内容
`getData(table,options){
 var knex=knex
   if(options.select)
   /** append the select data using knex.select()
   if(options.where)
   /** append the where data using knex.where(data)*/
   if(options.innerJoin)
   /** append innerjoin data*/
}`

通过这种方式,我可以避免编写大量数据库函数,并让我的业务逻辑层处理请求

1 个答案:

答案 0 :(得分:0)

/*This function serves as the core of our DB layer
This will generate a SQL query and execute it whilest returning the response prematurely
@param obj:{Object} this is the options object that contain all of the query options
@return Promise{Object}: returns a promise that will be reject or resolved based on the outcome of the query
The reasoning behind this kind of logic is that we want to abstract our layer as much as possible, if evne the slightest 
sytnax change occurs in the near future, we can easily update all our code by updating this one
We are using knex as a query builder and are thus relying on Knex to communicate with our DB*/
/*Can also be used to build custom query functions from a data.service. This way our database service will remain
unpolluted from many different functions and logic will be contained in a BLL*/
/* All available options
var options = {
    table:'table',
    where:{operand:'=',value:'value',valueToEqual:'val2'},
    andWhere:[{operand:'=',value:'value',valueToEqual:'val2'}],
    orWhere:[{operand:'=',value:'value',valueToEqual:'val2'}],
    select:{value:['*']},
    insert:{data:{}},
    innerJoin:[{table:'tableName',value:'value',valueToEqual:'val2'}],
    update:{data:{}}
}*/
/*Test object*/
/*var testobj = {
    table:'advantage',
    where:{operand:'>',value:'id',valueToEqual:'3'},
    select:{value:['*']},
    innerJoin:{table:'User_Advantage',value:'User_Advantage.Advantageid',valueToEqual:'id'}
}
var testobj = {
    table:'advantage',
    where:{operand:'>',value:'id',valueToEqual:'3'},
    select:{value:['*']},
    innerJoin:{table:'User_Advantage',value:'User_Advantage.Advantageid',valueToEqual:'id'}
}
queryBuilder(testobj)*/
function queryBuilder(options){
 var promise = new Promise(function (resolve, reject) {
    var query;
    for (var prop in options) {
        /*logger.info(prop)*/
        if (options.hasOwnProperty(prop)) {
            switch (prop) {
                case 'table':
                query = knex(options[prop]);
                break;
                case 'where':
                query[prop](options[prop].value, options[prop].operand, options[prop].valueToEqual);
                break;
                /*andWhere and orWhere share the same syntax*/
                case 'andWhere':
                case 'orWhere': 
                for(let i=0, len=options[prop].length;i<len;i++){
                    query[prop](options[prop][i].value, options[prop][i].operand, options[prop][i].valueToEqual);
                }
                break;
                case 'select':
                query[prop](options[prop].value);
                break;
                /*Same syntax for update and insert -- switch fallthrough*/
                case 'insert':
                case 'update':
                query[prop](options[prop].data);
                break;
                case 'innerJoin':
                for(let i=0, len=options[prop].length;i<len;i++){
                    query[prop](options[prop][i].table, options[prop][i].value, options[prop][i].valueToEqual);
                }
                break;
            }
        }
    }
    return query
    .then(function (res) {
        return resolve(res);
    }, function (error) {
        logger.error(error)
        return reject(error);
    })
    return reject('Options wrongly formatted');
});
 return promise
}

感谢Molda,我能够生成上面的代码。这个将一个名为options的Object作为参数,并根据该值构建knex链。请参阅有关Object语法的注释 并非每个knex查询选项都包含在内,但这对于任何试图达到类似效果的人来说都是一个很好的基础。

使用它的一些例子:

/*Will return all values from a certain table
@param: table{String}: string of the table to query
@param: select{Array[String]}: Array of strings of columns to be select -- defaults to ['*'] */
function getAll(table,select) {
    /*Select * from table as default*/
    var selectVal=select||['*']
    var options={
        table:table,
        select:{value:selectVal}
    }
    return queryBuilder(options)
}

或更具体的用例:

function getUserAdvantages(userid){
    var options = {
        table:'advantage',
        innerJoin:[{table:TABLE,value:'advantage.id',valueToEqual:'user_advantage.Advantageid'}],
        where:{operand:'=',value:'user_advantage.Userid',valueToEqual:userid}
    }
    return sqlService.queryBuilder(options)
}

注意:sqlService是我导出的包含queryBUilder方法的节点模块。

编辑:我想补充一点,我唯一的障碍就是使用Knex的.from / .insert。我不再使用这些方法,因为它们在使用时会导致错误。我用knex(表)作为评论。