Tips & Tricks

Guia practica de uso de Drizzle ORM con Claude Code

Una guia practica para usar Drizzle ORM con Claude Code, con ejemplos de codigo del mundo real.

Que es Drizzle ORM

Drizzle ORM es un ORM ligero orientado a TypeScript. Su caracteristica principal es que permite escribir consultas con seguridad de tipos usando una sintaxis cercana a SQL. Combinado con Claude Code, puede construir eficientemente la capa de base de datos.

Definicion de esquema

// 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(),
});

Definicion de relaciones

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],
  }),
}));

Operaciones de consulta

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 });

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

  return post;
}

// Busqueda (con paginacion)
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 };
}

// Actualizacion
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;
}

API de Relational Queries

// Consultas estilo Prisma
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,
      },
    },
  });
}

Migraciones

// 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;
# Generar migracion
npx drizzle-kit generate

# Aplicar migracion
npx drizzle-kit migrate

# Iniciar Drizzle Studio (GUI)
npx drizzle-kit studio

Comparacion con Prisma

CaracteristicaDrizzlePrisma
Tamano del bundleLigeroAlgo grande
Sintaxis de consultasCercana a SQLAPI propia
Soporte edgeExcelenteLimitado
Definicion de esquemaTypeScriptDSL propio
MigracionesGeneracion SQLGestion automatica

Uso con Claude Code

Ejemplo de como solicitar a Claude Code la implementacion con Drizzle ORM. Para comparacion con Prisma, consulte la guia completa de Prisma ORM. Para integracion con bases de datos, consulte tambien Desarrollo integrado con Supabase.

Construye la capa de base de datos con Drizzle ORM.
- Definicion de esquema para PostgreSQL
- Consultas CRUD con relaciones
- Paginacion y busqueda
- Configuracion de migraciones

Para mas detalles sobre Drizzle ORM, consulte la documentacion oficial de Drizzle ORM. Para el uso de Claude Code, consulte la documentacion oficial.

Resumen

Drizzle ORM es un ORM atractivo por su sintaxis cercana a SQL y su ligereza. Con Claude Code, puede implementar eficientemente consultas con seguridad de tipos y diseno de esquemas. Tambien es adecuado para uso en entornos edge.

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