Tips & Tricks

Panduan Praktis Using Drizzle ORM dengan Claude Code

Panduan praktis tentang using drizzle orm menggunakan Claude Code dengan contoh kode dunia nyata.

Drizzle ORM

Drizzle ORM TypeScriptファースト 軽量ORM.SQL 近い記法 type safetyなquery 書ける fitur.Claude Code dan 組み合わせれば、efisien database層 pembangunan bisa dilakukan.

Definisi Skema

// db/schema.ts
import {
  pgTable,
  text,
  timestamp,
  boolean,
  integer,
  varchar,
  index,
} from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";

export const users = pgTable("users", {
  id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
  email: varchar("email", { length: 255 }).notNull().unique(),
  name: varchar("name", { length: 100 }).notNull(),
  avatar: text("avatar"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  updatedAt: timestamp("updated_at").defaultNow().notNull(),
}, (table) => ({
  emailIdx: index("email_idx").on(table.email),
}));

export const posts = pgTable("posts", {
  id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
  title: varchar("title", { length: 255 }).notNull(),
  content: text("content").notNull(),
  published: boolean("published").default(false).notNull(),
  authorId: text("author_id").notNull().references(() => users.id),
  viewCount: integer("view_count").default(0).notNull(),
  publishedAt: timestamp("published_at"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
}, (table) => ({
  authorIdx: index("author_idx").on(table.authorId),
  publishedIdx: index("published_idx").on(table.published, table.publishedAt),
}));

export const comments = pgTable("comments", {
  id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
  content: text("content").notNull(),
  authorId: text("author_id").notNull().references(() => users.id),
  postId: text("post_id").notNull().references(() => posts.id, { onDelete: "cascade" }),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

リレーションdefinisi

export const usersRelations = relations(users, ({ many, one }) => ({
  posts: many(posts),
  comments: many(comments),
}));

export const postsRelations = relations(posts, ({ one, many }) => ({
  author: one(users, {
    fields: [posts.authorId],
    references: [users.id],
  }),
  comments: many(comments),
}));

export const commentsRelations = relations(comments, ({ one }) => ({
  author: one(users, {
    fields: [comments.authorId],
    references: [users.id],
  }),
  post: one(posts, {
    fields: [comments.postId],
    references: [posts.id],
  }),
}));

queryoperasi

import { drizzle } from "drizzle-orm/node-postgres";
import { eq, and, like, desc, sql, count } from "drizzle-orm";
import * as schema from "./schema";

const db = drizzle(pool, { schema });

// 挿入
async function createPost(data: {
  title: string;
  content: string;
  authorId: string;
}) {
  const [post] = await db
    .insert(posts)
    .values(data)
    .returning();

  return post;
}

// pencarian(pagination付き)
async function getPosts(params: {
  page?: number;
  perPage?: number;
  search?: string;
}) {
  const { page = 1, perPage = 20, search } = params;

  const conditions = [eq(posts.published, true)];
  if (search) {
    conditions.push(like(posts.title, `%${search}%`));
  }

  const [data, [{ total }]] = await Promise.all([
    db
      .select({
        id: posts.id,
        title: posts.title,
        publishedAt: posts.publishedAt,
        authorName: users.name,
        commentCount: count(comments.id),
      })
      .from(posts)
      .leftJoin(users, eq(posts.authorId, users.id))
      .leftJoin(comments, eq(posts.id, comments.postId))
      .where(and(...conditions))
      .groupBy(posts.id, users.name)
      .orderBy(desc(posts.publishedAt))
      .limit(perPage)
      .offset((page - 1) * perPage),

    db
      .select({ total: count() })
      .from(posts)
      .where(and(...conditions)),
  ]);

  return { data, total, page, perPage };
}

// pembaruan
async function updatePost(id: string, data: Partial<typeof posts.$inferInsert>) {
  const [updated] = await db
    .update(posts)
    .set({ ...data, updatedAt: new Date() })
    .where(eq(posts.id, id))
    .returning();

  return updated;
}

Relational Queries API

// Prismaライクなquery
async function getPostWithRelations(id: string) {
  return db.query.posts.findFirst({
    where: eq(posts.id, id),
    with: {
      author: {
        columns: { id: true, name: true, avatar: true },
      },
      comments: {
        with: {
          author: {
            columns: { id: true, name: true },
          },
        },
        orderBy: [desc(comments.createdAt)],
        limit: 10,
      },
    },
  });
}

Migrasi

// drizzle.config.ts
import type { Config } from "drizzle-kit";

export default {
  schema: "./db/schema.ts",
  out: "./drizzle",
  dialect: "postgresql",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
} satisfies Config;
# マイグレーション生成
npx drizzle-kit generate

# マイグレーション適用
npx drizzle-kit migrate

# Drizzle Studio(GUI)起動
npx drizzle-kit studio

比較 Prisma

特性DrizzlePrisma
bundleサイズ軽量やや大きい
query記法SQL寄り独自API
エッジdukungan優秀制限あり
スキーマdefinisiTypeScript独自DSL
マイグレーションSQLgenerate自動manajemen

Pemanfaatan dengan Claude Code

Drizzle ORM implementasi Claude Code 依頼 例.Prisma dan 比較 Prisma ORM完全panduan、databaseintegrasi mengenai Supabaseintegrasipengembangan juga bisa dijadikan referensi.

Drizzle ORM dengan database層 bangun.
- PostgreSQL スキーマdefinisi
- リレーション付き CRUDquery
- pagination dan pencarian
- マイグレーションpengaturan

Drizzle ORM 詳細 Drizzle ORM公式dokumen silakan lihat.Claude Code pemanfaatan法 公式dokumen konfirmasi bisa dilakukan.

Summary

Drizzle ORM SQL 近い記法 dan 軽量さ 魅力 ORM.Claude Code 使えば、type safetyなquery dan スキーマ設計 efisien implementasi bisa dilakukan.エッジ環境 pemanfaatan juga 適 い.

#Claude Code #Drizzle ORM #database #TypeScript #SQL