如果我更喜欢使用raw而不是它的内置函数,那么使用knex是没有意义的吗?

d5vmydt9  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(341)

我知道knex有各种好处,这就是为什么我考虑将其用于我的节点应用程序。我以前用过它,我非常喜欢用它编写原始查询(注意:对于knex,我还处于学习阶段。)我个人认为,它们使代码看起来比使用basicsql稍微好一些。我的问题就是从这一点开始的,因为也许我的偏好在这里是愚蠢的。
我也很想对knex的内置函数发表意见。对于那些更喜欢使用生的,你喜欢他们什么?我的目标是在我的应用程序的一致性,无论我选择的路线。
谢谢你的意见!

qvsjd97n

qvsjd97n1#

这不是毫无意义的。这在一定程度上取决于您是否在团队环境中工作,还有谁可能需要维护它,以及他们对编写sql查询的适应程度。请注意,knex可以完成的许多事情也可以通过直接数据库驱动程序来完成,因此对于许多技术选择,它归结为个人/团队偏好和易于维护。
即使您从未使用过查询生成器,knex也提供了:
根据目前的情况,配置相对简单 NODE_ENV 连接/池管理
易于参数化
轻松的交易
易于迁移和播种
为什么不用 .raw ? 好吧,这是品尝者的选择,而查询生成器并不适合所有人。不过,query builder的粉丝会告诉你:
当您不处理一堆原始sql时,在数据库后端之间迁移会更容易
许多人认为knex语法更容易阅读,因为能够合理理解javascript承诺链的人可能比那些喜欢使用sql的人多
它往往比较紧凑
它提供了一定级别的名称/语法安全性(如果您使用的是typescript,还提供了transfile-time类型安全性和编辑器支持) .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);

这是一个精心设计的示例,但在处理不那么琐碎的需求时,它可以非常有表现力。

voase2hg

voase2hg2#

我知道这篇文章有点老,但我同意混合方法。在某些情况下,查询生成器语法为正在编写的“错误”查询提供了良好的反馈,这是非常好的。
另一方面,我有一些查询,我认为使用生成器编写会变得太冗长,所以我使用 .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);

相关问题