如果我更喜欢使用原始而不是其内置函数,那么使用 Knex 是否毫无意义?



我知道 Knex 有很多好处,这就是为什么我考虑将它用于我的 Node 应用程序。我以前用过它,我真的很喜欢用它编写原始查询。(注意:我仍处于学习Knex的阶段。就个人而言,我认为它们使代码看起来比使用基本SQL略好。我的问题正是从这一点开始的,因为也许我的偏好在这里很愚蠢。

我也喜欢对 Knex 内置函数的意见。对于那些喜欢那些使用原始的人,你喜欢他们的什么?无论我选择哪种路线,我的目标都是我的应用程序的一致性。

感谢您的输入!

这不是没有意义的。这有点取决于您是否在团队环境中工作,还有谁可能必须维护它,以及他们对编写SQL查询的舒适度。请注意,许多可以使用 Knex 完成的事情也可以使用直接数据库驱动程序完成,因此与许多技术选择一样,它归结为个人/团队偏好和易于维护。

即使假设您从未使用过查询构建器,Knex 也会提供:

  • 根据当前NODE_ENV配置相对简单
  • 连接/池管理
  • 轻松设置参数
  • 轻松交易
  • 轻松迁移和播种

为什么不使用.raw?好吧,这是品尝者的选择,查询构建器并不适合所有人。但是,查询生成器的粉丝会告诉您:

  • 当您不处理一堆原始 SQL 时,在数据库后端之间迁移会更容易
  • 许多人发现 Knex 语法更容易阅读,因为能够合理理解 JavaScript 承诺链的人可能比那些理解 SQL 的人多
  • 它往往更紧凑
  • 它提供了一定程度的名称/语法安全(如果您使用的是 TypeScript,则提供转译时间类型安全和编辑器支持(,超过.raw.

查询构建器也非常适合组合,因此

const userPhoneNumbers = knex('users').select({ id, email });
// later...
const gmailUsers = userPhoneNumbers.where('email', 'ilike', '%gmail.com');
// still later...
return gmailUsers.where('email_confirmed', true);

一个人为的例子,但在处理不太琐碎的要求时,它可以非常有表现力。

我知道这篇文章有点旧,但我同意混合方法。 在某些情况下,查询生成器语法为正在编写的"错误"查询提供了良好的反馈,这很棒。

另一方面,我有一些查询,我认为使用构建器编写会变得过于冗长,所以我使用.raw. 下面是一个查询示例,我认为该查询保留在.raw格式中。

select
s.client_id,
s.package_id,
p.products as pp,
s.products as sp
from (
# grouped subscribed products
select
client_id,
package_id,
group_concat(product_id order by product_id) as products
from subscriptions where package_id is not null
group by client_id, package_id) as s
inner join (
# grouped package products
select
package_id,
group_concat(product_id order by product_id) as products
from package_products
group by package_id) as p
on p.package_id = s.package_id where p.products <> s.products
order by s.client_id

我当然可以使用构建器,但我发现使用嵌套选择更容易掌握原始 SQL。 我还创建了一个抽象类来简化为微型ORM。

class Table {
constructor() {
// nothing
}
static tableName = null;
/**
* Find by id
* @param {Integer} userId
* @return {Promise}
*
* Example:
* Table.findById(id).then(result => {
*   console.log(result)
* }).catch(err => {
*   console.error(err);
* })
*/
static findById(itemId) {
return this.findOneBy({id: itemId});
}
/**
* Generic findBy
* @param {String|Object} column or objcet with keys
* @param {Any} value
*/
static findOneBy(column, value = null) {
return this.findBy(column, value).then(results => {
return results[0];
});
}
/**
* Generic findBy
* @param {String|Object} column or objcet with keys
* @param {Any} value
*/
static findBy(column, value = null) {
return database.getConnection().then(conn => {
const schema = this.schemaName;
const query = conn.select().from(this.tableName);
if (schema){
query.withSchema(schema);
}
if (typeof column === 'object '&& !Array.isArray(column) && value === null) {
for (const col in column) {
query.where(col, column[col]);
}
} else {
query.where(column, value);
}
return query;
});
}
}

这允许我使用以下方法创建模型:

class Client extends Table {
static tableName = 'clients';
constructor() {
super();
}
}
Client.findById(1).then(result => {
console.log(result);
}).catch(console.error);

最新更新