Drizzle ORM
規則
- 結構定義:在
src/db/schema.ts 中使用 pgTable() / mysqlTable() / sqliteTable()
- 開發階段:使用
drizzle-kit push 快速迭代 — 無需遷移檔案
- 生產環境:使用
drizzle-kit generate + drizzle-kit migrate 以產生可追蹤的遷移歷史
- 型別安全查詢:
db.select().from(users).where(eq(users.email, email)) — 完整 TypeScript 推論
- 關聯:使用
relations() 輔助函式定義 — 搭配 one() 和 many() 進行 db.query 的關聯查詢
- 預備陳述式:
db.select().from(users).where(eq(users.id, sql.placeholder("id"))).prepare() — 在熱點路徑重複使用
- 交易:
db.transaction(async (tx) => { ... }) — 在回呼內部使用 tx 而非 db
- 索引:在行內使用
.index() 或在表格設定中定義 — 在 where 和 orderBy 中用到的欄位上新增
- Drizzle Studio:
npx drizzle-kit studio — 開發期間的視覺化資料庫瀏覽器
模式
import { pgTable, text, timestamp, uuid, integer } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
export const users = pgTable("users", {
id: uuid("id").primaryKey().defaultRandom(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export const posts = pgTable("posts", {
id: uuid("id").primaryKey().defaultRandom(),
title: text("title").notNull(),
authorId: uuid("author_id").references(() => users.id).notNull(),
});
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, { fields: [posts.authorId], references: [users.id] }),
}));
const result = await db.query.users.findFirst({
where: eq(users.id, userId),
with: { posts: true },
});
避免
- 在生產環境使用
drizzle-kit push — 改使用 generate + migrate 以進行受控的遷移
- 在 Drizzle API 已涵蓋的情況下使用原始 SQL — 僅在複雜表達式中使用
sql 模板標籤
- 遺漏
relations() 定義 — 若缺少定義,db.query 的關聯查詢將無法運作
- N+1 查詢 — 在
db.query 中使用 with 以在單一查詢中聯結關聯
- 在外鍵與篩選欄位上遺漏索引 — Drizzle 不會自動建立它們