Node.js Knex.js:強大的 SQL 查詢產生器與資料庫管理

雖然 MongoDB (NoSQL) 非常流行,但在處理具有複雜關聯、交易 (Transaction) 需求或嚴謹 Schema 的企業級應用時,關係型資料庫 (SQL) 如 MySQL、PostgreSQL 仍是首選。Knex.js 則是 Node.js 生態系中最老牌且穩定的「查詢產生器 (Query Builder)」。

為什麼選擇 Knex.js?

  1. 語法通用:使用一套 JavaScript 語法即可生成各類 SQL (MySQL, PgSQL, SQLite),降低切換成本。
  2. 安全防禦:預設使用參數化查詢,有效防止 SQL 注入 (SQL Injection) 攻擊。
  3. 結構版本控制 (Migrations):讓你用程式碼來追蹤資料庫結構的變動,避免手動改表的風險。

安裝與初始化

安裝 Knex 核心以及對應的資料庫驅動(以 MySQL 為例):

npm install knex mysql2

建立一個 knexfile.js 檔案來管理連線配置:

module.exports = {
  development: {
    client: 'mysql2',
    connection: {
      host: '127.0.0.1',
      user: 'root',
      password: 'your_password',
      database: 'my_blog_db',
    },
    pool: { min: 2, max: 10 }, // 連線池配置
  },
};

基本查詢:像寫 JS 一樣寫 SQL

const knex = require('knex')(require('./knexfile').development);

async function getRecentPosts() {
  // 對等:SELECT id, title FROM posts WHERE status = 'published' ORDER BY id DESC LIMIT 5
  const posts = await knex('posts')
    .select('id', 'title', 'content')
    .where('status', 'published')
    .andWhere('author_id', 1)
    .orderBy('id', 'desc')
    .limit(5);

  return posts;
}

進階:資料庫遷移 (Migrations)

Migration 就像是資料庫的 Git。它紀錄了表結構的演進過程。

建立遷移檔

npx knex migrate:make create_posts_table

定義結構 (migrations/xxxxx_create_posts_table.js)

exports.up = function (knex) {
  return knex.schema.createTable('posts', (table) => {
    table.increments('id'); // 自動遞增 ID
    table.string('title').notNullable();
    table.text('content');
    table.integer('author_id').unsigned().references('users.id');
    table.timestamps(true, true); // 建立 created_at 與 updated_at
  });
};

exports.down = function (knex) {
  return knex.schema.dropTable('posts');
};
  • 執行遷移npx knex migrate:latest
  • 復原遷移npx knex migrate:rollback

高階重點:交易 (Transactions)

當你需要同時執行多個寫入操作(如轉帳:扣款 A 的同時增加 B 的餘額),務必使用 Transaction,確保「要嘛全部成功,要嘛全部失敗」。

try {
  await knex.transaction(async (trx) => {
    await trx('accounts').where('id', 1).decrement('balance', 100);
    await trx('accounts').where('id', 2).increment('balance', 100);
  });
  console.log('轉帳成功');
} catch (err) {
  console.error('轉帳失敗,已自動回滾 (Rollback)');
}

總結

  1. Knex.js 適合不喜歡過度包裝 (ORM),但又想要安全、靈活操作 SQL 的開發者。
  2. 養成使用 Migrations 的習慣,這能讓你的團隊成員輕鬆同步資料庫結構。
  3. 處理多表寫入時,務必養成使用 Transaction 的好習慣。