首页 > 解决方案 > 动态创建 .where 函数 knexjs

问题描述

有没有办法.while与 knex 一起动态使用?我有以下内容:

const user = await Users.findOne({id}, "id username email");

哪个

findOne(data, returns) {
    return knex("users").select(returns && typeof returns === "string" ? returns.split(" ") : "*").where(data).first();
}

这很好用。如果我想匹配,我可以这样做idusername

const user = await Users.findOne({id, username}, "id username email");

但是,我需要username不区分大小写。使用 mongo (Mongoose),我会这样做:

{username: new RegExp("^" + username + "$", "I")}但使用 knex 查询实验室: http : //michaelavila.com/knex-querylab/where username = {}

所以我发现我需要where username ilike %username%在 knex 中做

.where('username', 'ilike', `%${username}%`)

所以我有一个新功能:

//users route
const  user = await Users.findOneByArray(['username', 'ilike', `%${username}%`]);

//queries file
findOneByArray(data) {
    return knex("users").where(...data).first();
}

不过,这个问题是,如果我现在有多个查询,我不能像处理对象那样下一步。我目前正在为更复杂的查询做的是这种混乱:

//users route
const user = await Users.findTokenMatchesAccount(['id', '=', `${token.user_id}`], ['username', 'ilike', `%${username}%`], ['email', 'ilike', `%${email}%`]);

//query file
findTokenMatchesAccount(id, username, email) {
    return knex("users").where(...id).where(...username).where(...email).first();
}

3个人.where给他们。是否有某种方法可以自动/动态地创建 where 函数,例如:

//users route
const user = await Users.findTokenMatchesAccount([['id', '=', `${token.user_id}`], ['username', 'ilike', `%${username}%`], ['email', 'ilike', `%${email}%`]]);

//query file
findTokenMatchesAccount(data) {
    return knex("users").where(function() {
        for(const i in data) return(where(data[i])}).first();
    }
}

获取数据参数中的所有值并动态添加.where到其中的一些魔法。还是我必须手动设置它作为我可能需要的任何查询的一部分?(.where如上所示 3 秒,.where如果我有其他不区分大小写的选项要查找,下次可能需要 4 秒)

还是更容易获取数据数组并创建字符串并使用knex.raw?不过,我不确定那会逃脱drop table.

标签: node.jspostgresqlknex.js

解决方案


似乎 knex 是使用 Builder Pattern 实现的。也许尝试利用.reduce()?它通常用于链接/创建管道。

async function findTokenMatchesAccount(whereStmtArgs) {
  // Store the query
  let query = knex('users');

  // Pick one from the 2 options:  

  // Option 1
  whereStmtArgs.reduce((q, currentWhereStmtArg) => q.where(...currentWhereStmtArg), query);

  // Option 2 (if you're not comfortable with reduce)
  for (const whereStmtArg for whereStmtArgs) {
    query = query.where(...whereStmtArg);
  }

  return query.first();
}

const dynamicWhereStatements = [['id', '=', `${token.user_id}`], ['username', 'ilike', `%${username}%`], ['email', 'ilike', `%${email}%`]];
const user = await findTokenMatchesAccount(dynamicWhereStatements);

推荐阅读