Knex查询构建 - 动态构建链

问题描述:

我已经为knex交易了节点DBI,因为它具有我需要的更多功能。 到目前为止,我会再次做出同样的选择,但只有一件事情让我失望:编写抽象方法,其中包含像params这样的参数,innerjoin等参数。 使用node-dbi我可以很容易地伪造字符串使用这些变量,但我似乎无法动态地创建knex链,因为使用开关后,你会得到knex.method不是一个函数。Knex查询构建 - 动态构建链

任何想法如何解决这个问题?

我在寻找的东西,如

`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*/ 
}` 

这样我可不必写很多的DB功能,让我的业务逻辑层次韩德尔的要求

+0

我不知道我的理解是否正确,但我相信你可以做类似'var query = knex('users_table');如果(options.select)query.select(...)' – Molda

+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的对象作为参数,并将根据此值构建knex链。查看对象 的语法注释并非每个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(表)作为评论。

+0

另请注意,订单非常重要。就像在SQL中一样,你的表和连接应该是第一位的! –