Drizzle ORM
Drizzle ORMは、SQL中心のTypeScript ORMです。軽量で依存関係ゼロ、Serverless環境に最適化されており、「SQLを知っていればDrizzleも知っている」をコンセプトに、高いパフォーマンスと直感的なAPI設計を両立したHeadless ORMです。
GitHub概要
drizzle-team/drizzle-orm
Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
スター29,260
ウォッチ55
フォーク936
作成日:2021年6月24日
言語:TypeScript
ライセンス:Apache License 2.0
トピックス
bunjsd1libsqllitefsmysqlmysql2neonnodejsormpostgrespostgresjspostgresqlsqlsqlitesqlite3sqljstursotypescriptvercel-postgres
スター履歴
データ取得日時: 2025/7/17 10:32
ライブラリ
Drizzle ORM
概要
Drizzle ORMは、SQL中心のTypeScript ORMです。軽量で依存関係ゼロ、Serverless環境に最適化されており、「SQLを知っていればDrizzleも知っている」をコンセプトに、高いパフォーマンスと直感的なAPI設計を両立したHeadless ORMです。
詳細
Drizzleは従来のORMとは異なり、SQL-firstアプローチを採用しています。SQLを抽象化するのではなく、SQLの力を活用しながらTypeScriptの型安全性を提供します。これにより、パフォーマンスを犠牲にすることなく、開発者の生産性を向上させます。
主な特徴
- SQL-first設計: 生のSQLに近い記述で高性能なクエリ
- ゼロ依存関係: 軽量で高速、バンドルサイズを最小化
- 型安全性: 完全なTypeScript統合
- Serverless最適化: Edge Computing環境での優秀な動作
- マイグレーション: スキーマドリブンな安全なデータベース変更
メリット・デメリット
メリット
- 軽量で高速、特にServerless環境での優秀なパフォーマンス
- SQLに慣れた開発者にとって学習コストが非常に低い
- 完全な型安全性でランタイムエラーを削減
- 依存関係なしでプロジェクトのセキュリティリスクを軽減
- Edge ComputingやCloudflare Workersで最適化された動作
デメリット
- まだ比較的新しいため、エコシステムが発展途上
- ActiveRecordパターンに慣れた開発者には学習が必要
- ORM機能は最小限でよりSQLの知識が求められる
- 複雑なリレーションシップ操作では手動でのクエリ構築が必要
参考ページ
書き方の例
インストールと基本セットアップ
npm install drizzle-orm drizzle-kit
npm install @types/pg pg # PostgreSQLの場合
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/schema.ts',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
verbose: true,
strict: true,
});
基本的なCRUD操作
// schema.ts
import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').notNull().unique(),
createdAt: timestamp('created_at').defaultNow(),
});
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
authorId: integer('author_id').references(() => users.id),
createdAt: timestamp('created_at').defaultNow(),
});
// データベース操作
import { drizzle } from 'drizzle-orm/node-postgres';
import { Client } from 'pg';
import { users, posts } from './schema';
const client = new Client({
connectionString: process.env.DATABASE_URL,
});
const db = drizzle(client);
// 作成
const newUser = await db.insert(users).values({
name: '田中太郎',
email: '[email protected]'
}).returning();
// 読み取り
const allUsers = await db.select().from(users);
// 更新
await db.update(users)
.set({ name: '田中次郎' })
.where(eq(users.id, 1));
// 削除
await db.delete(users).where(eq(users.id, 1));
高度なクエリとリレーションシップ
import { eq, sql } from 'drizzle-orm';
// JOINクエリ
const usersWithPosts = await db
.select({
userId: users.id,
userName: users.name,
postTitle: posts.title,
postCount: sql<number>`count(${posts.id})`,
})
.from(users)
.leftJoin(posts, eq(users.id, posts.authorId))
.groupBy(users.id)
.having(sql`count(${posts.id}) > 0`);
// 複雑な条件クエリ
const activeUsers = await db
.select()
.from(users)
.where(
and(
gt(users.createdAt, sql`NOW() - INTERVAL '30 days'`),
like(users.email, '%@company.com')
)
)
.orderBy(desc(users.createdAt))
.limit(10);
// サブクエリ
const sq = db
.select({ count: sql<number>`count(*)` })
.from(posts)
.where(eq(posts.authorId, users.id))
.as('post_count');
const usersWithPostCounts = await db
.select({
user: users,
postCount: sq.count,
})
.from(users)
.leftJoin(sq, eq(users.id, sq.authorId));
マイグレーションとスキーマ管理
# マイグレーション生成
npx drizzle-kit generate
# マイグレーション適用
npx drizzle-kit migrate
// 手動マイグレーション実行
import { migrate } from 'drizzle-orm/node-postgres/migrator';
await migrate(db, { migrationsFolder: './drizzle' });
パフォーマンス最適化と高度な機能
// プリペアドステートメント
const getUserById = db
.select()
.from(users)
.where(eq(users.id, placeholder('id')))
.prepare();
const user = await getUserById.execute({ id: 1 });
// トランザクション
await db.transaction(async (tx) => {
const user = await tx.insert(users).values({
name: '山田花子',
email: '[email protected]'
}).returning();
await tx.insert(posts).values({
title: '最初の投稿',
content: 'Drizzleを使った投稿です',
authorId: user[0].id
});
});
// バッチ操作
await db.insert(users).values([
{ name: 'ユーザー1', email: '[email protected]' },
{ name: 'ユーザー2', email: '[email protected]' },
{ name: 'ユーザー3', email: '[email protected]' },
]);
フレームワーク統合と実用例
// Next.js App Router統合
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { users } from '@/lib/schema';
export async function GET() {
try {
const allUsers = await db.select().from(users);
return NextResponse.json(allUsers);
} catch (error) {
return NextResponse.json(
{ error: 'ユーザーの取得に失敗しました' },
{ status: 500 }
);
}
}
// Cloudflare Workers統合
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const db = drizzle(env.DB);
const users = await db.select().from(usersTable);
return Response.json(users);
}
};