Tutorial básico de Drizzle ORM

Aprende los conceptos básicos de Drizzle ORM, una herramienta ORM ligera para JavaScript y TypeScript, que te permite interactuar con bases de datos de manera sencilla y eficiente.

Sergio Gallardo··Desarrollo

En este tutorial, aprenderás los conceptos básicos de Drizzle ORM, una herramienta ORM ligera para JavaScript y TypeScript. Drizzle ORM te permite interactuar con bases de datos de manera sencilla y eficiente, utilizando un enfoque basado en objetos.

Entre sus características principales se incluyen:

  • Simplicidad: Drizzle ORM tiene una API intuitiva y fácil de usar, que además se asemeja a SQL puro (aunque también tiene otra modalidad de uso más orientada a objetos donde no se necesita pensar en "joins" o mapeo de datos).
  • Compatibilidad: Drizzle ORM es compatible con múltiples bases de datos, por ejemplo PostgreSQL, MySQL, SQLite y recientemente también MSSQL. Esta compatibilidad también incluye a sus versiones en la nube como Neon, PlanetScale, Turso o Supabase. (Para el listado completo de bases de datos compatibles, puedes consultar la documentación oficial.)
  • Sin dependencias: Drizzle ORM no tiene dependencias externas, lo que lo hace ligero y fácil de integrar en cualquier proyecto. Esta característica permite que se ejecute en una gran variedad de ambientes como lo son NodeJS, Bun, AWS Lambda, Cloudflare Workers, Deno, incluso en el propio navegador y hasta en entornos de Edge Computing y aplicaciones de renderizado nativo como las creadas con React Native.

Estructura del proyecto

Antes de comenzar, es importante entender la estructura básica de un proyecto que utiliza Drizzle ORM. A continuación, se muestra una estructura típica de un proyecto:

. <project>
├─ drizzle
├─ src
│   ├─ db
│   │  ├─ database.ts
│   │  └─ schema.ts
│   └─ index.ts
├─ .env
├─ drizzle.config.ts
├─ package.json
└─ tsconfig.json

Para comenzar crea un nuevo proyecto de TypeScript y luego continúa con los siguientes pasos.

Instalación

El primer paso para comenzar es instalar Drizzle ORM en tu proyecto. Para este tutorial por simplicidad estaremos utilizando la base de datos SQLite con el driver libsql. Toma en cuenta que si quieres utilizar otra base de datos tendrás que instalar otro driver y realizar la configuración específica para la base de datos que selecciones. Para iniciar con nuestra instalación puedes hacerlo utilizando la herramienta de manejo de paquetes de tu runtime favorito, por ejemplo:

# npm
npm install drizzle-orm @libsql/client dotenv
npm install -D drizzle-kit tsx

# pnpm
pnpm add drizzle-orm @libsql/client dotenv
pnpm add -D drizzle-kit tsx

# yarn
yarn add drizzle-orm @libsql/client dotenv
yarn add --dev drizzle-kit tsx

# bun
bun add drizzle-orm @libsql/client
bun add --dev drizzle-kit

Configuración

Una vez que hayas instalado Drizzle ORM, el siguiente paso es configurar la conexión a tu base de datos. Una buena práctica es utilizar variables de entorno para almacenar la información de la conexión. Crea un archivo .env en la raíz de tu proyecto y agrega la siguiente línea, reemplazando los valores con los de tu base de datos:

.env
DB_FILE_NAME=file:local.db

Con esta configuración, estamos indicando que queremos utilizar una base de datos SQLite almacenada en un archivo llamado local.db. Si estás utilizando otra base de datos, la cadena de conexión será diferente, por ejemplo para PostgreSQL podría ser algo como postgresql://user:password@localhost:5432/mydatabase.

Luego, crea un archivo database.ts para configurar la conexión a la base de datos utilizando Drizzle ORM:

src/db/database.ts
import "dotenv/config";
import { drizzle } from "drizzle-orm/libsql";

const dbFileName = process.env.DB_FILE_NAME;
if (!dbFileName) {
	throw new Error("DB_FILE_NAME environment variable is not set");
}

export const db = drizzle(dbFileName);

En este archivo, importamos la función drizzle del paquete drizzle-orm/libsql y la utilizamos para crear una instancia de conexión a la base de datos utilizando la cadena de conexión almacenada en la variable de entorno DB_FILE_NAME.

Definición de esquemas

Los esquemas en Drizzle ORM se definen utilizando la función sqliteTable (o mysqlTable, pgTable, etc., dependiendo de la base de datos que estés utilizando). Esta función te permite definir la estructura de tus tablas y sus relaciones. Por ejemplo, si queremos definir una tabla de autores, podríamos hacerlo de la siguiente manera:

src/db/schema.ts
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";

export const authors = sqliteTable("authors", {
	id: integer("id").primaryKey({ autoIncrement: true }),
	name: text("name").notNull(),
	email: text("email").notNull().unique(),
});

En este ejemplo, estamos definiendo una tabla llamada authors con tres columnas: id, name y email. La columna id es un campo de tipo entero que se autoincrementa y se establece como llave primaria. Las columnas name y email son de tipo texto, no pueden ser nulas, y la columna email debe ser única.

Uso de Drizzle Kit

Drizzle Kit es una herramienta de línea de comandos que te permite gestionar tus migraciones y generar las tablas en la base de datos automáticamente a partir de tus esquemas. Para configurar Drizzle Kit, crea un archivo drizzle.config.ts en la raíz de tu proyecto con el siguiente contenido:

drizzle.config.ts
import "dotenv/config";
import { defineConfig } from "drizzle-kit";

export default defineConfig({
	schema: "./src/db/schema.ts",
	out: "./drizzle",
	dialect: "sqlite",
	dbCredentials: {
		url: process.env.DB_FILE_NAME || "",
	},
});

En este archivo, estamos indicando a Drizzle Kit dónde se encuentra nuestro esquema (./src/db/schema.ts), dónde queremos que se generen las migraciones (./drizzle), qué dialecto estamos utilizando (sqlite) y los parámetros de conexión a la base de datos. Necesitamos configurarlo para poder generar la tabla en la base de datos a partir del esquema que definimos.

Una vez que hayas configurado Drizzle Kit, puedes crear la tabla en la base de datos ejecutando el siguiente comando:

# npm
npx drizzle-kit push

# pnpm
pnpm drizzle-kit push

# yarn
yarn drizzle-kit push

# bun
bun drizzle-kit push

Toma en cuenta

El comando drizzle-kit push que utilizamos acá es más bien para ambiente de desarrollo desarrollo, ya que aplica los cambios del esquema directamente a la base de datos sin generar archivos de migración. Para producción, es preferible usar drizzle-kit generate y drizzle-kit migrate, que generan y aplican migraciones de forma controlada.

Operaciones CRUD básicas

Ahora que tenemos nuestra tabla creada, podemos comenzar a realizar operaciones CRUD (Crear, Leer, Actualizar, Eliminar) utilizando Drizzle ORM.

Crear un nuevo registro

Primero vamos a crear un archivo index.ts donde vamos a escribir nuestro código para interactuar con la base de datos:

src/index.ts
import { eq } from "drizzle-orm";
import { db } from "./db/database";
import { authors } from "./db/schema";

async function main() {
	// Crear una pareja de nuevos autores
	const newAuthor = await db
		.insert(authors)
		.values({
			name: "Pedro Pablo",
			email: "pedro.pablo@example.com",
		})
		.returning();
	console.log("Nuevo autor creado:", newAuthor);

	const secondNewAuthor = await db
		.insert(authors)
		.values({
			name: "Jose Juan",
			email: "jose.juan@example.com",
		})
		.returning();
	console.log("Segundo autor creado:", secondNewAuthor);
}

main();

En este ejemplo, estamos utilizando el método insert para crear una pareja de nuevos autores en la tabla authors. El método values se utiliza para especificar los valores que queremos insertar, y el método returning nos permite obtener el registro recién creado. Desde la raíz de tu proyecto puedes ejecutar este código utilizando el siguiente comando:

# npm
npx tsx src/index.ts

# pnpm
pnpm tsx src/index.ts

# yarn
yarn tsx src/index.ts

# bun
bun src/index.ts

Si todo ha ido bien, deberías ver en la consola unos mensajes indicando que los nuevos autores han sido creados, junto con los detalles del registro.

Leer registros

Para leer registros de la base de datos, puedes utilizar el método select. Por ejemplo, para obtener todos los autores de la tabla authors, puedes hacer lo siguiente:

src/index.ts

  // ... código anterior

	// Leer todos los autores
	const allAuthors = await db.select().from(authors);
	console.log("Todos los autores:", allAuthors);
}

main();

El resultado se almacena en la variable allAuthors, que luego se muestra en la consola. Para filtrar los resultados, puedes utilizar el método where. Por ejemplo, para obtener un autor específico por su correo electrónico, puedes hacer lo siguiente:

src/index.ts

  // ... código anterior

	// Leer un autor por correo electrónico
	const author = await db
		.select()
		.from(authors)
		.where(eq(authors.email, "pedro.pablo@example.com"));
	console.log("Autor encontrado:", author);
}

main();

Actualizar un registro

Para actualizar un registro en la base de datos, puedes utilizar el método update. Por ejemplo, para actualizar el nombre de un autor específico, puedes hacer lo siguiente:

src/index.ts

  // ... código anterior

	// Actualizar el nombre de un autor
	const updatedAuthor = await db
		.update(authors)
		.set({
			name: "Pedro P.",
		})
		.where(eq(authors.email, "pedro.pablo@example.com"));
	console.log("Autor actualizado:", updatedAuthor);
}

main();

Eliminar un registro

Para eliminar un registro de la base de datos, puedes utilizar el método delete. Por ejemplo, para eliminar un autor específico, puedes hacer lo siguiente:

src/index.ts

  // ... código anterior

	// Eliminar un autor
	const deletedAuthor = await db
		.delete(authors)
		.where(eq(authors.email, "pedro.pablo@example.com"));
	console.log("Autor eliminado:", deletedAuthor);
}

main();

Conclusión

En este tutorial, hemos cubierto los conceptos básicos de Drizzle ORM, incluyendo cómo configurar la conexión a la base de datos, definir esquemas, utilizar Drizzle Kit para la creación y actualización de la base de datos y realizar operaciones CRUD básicas. Drizzle ORM es una herramienta poderosa y flexible que puede ayudarte a interactuar con tu base de datos de manera eficiente y sencilla. A medida que te familiarices más con Drizzle ORM, podrás explorar características más avanzadas como relaciones entre tablas, transacciones, consultas complejas y migraciones. Puedes encontrar el código completo de este tutorial en el siguiente repositorio de GitHub.