Weadb Notes

Drizzle-orm 与 cloudflare D1 使用基础

26 天前·8 min read

将 Drizzle ORM 与 Cloudflare D1(基于 SQLite 的分布式数据库)结合使用,是目前 Cloudflare Workers/Pages 生态中非常流行的数据持久化方案。

由于 D1 运行在 Cloudflare 的边缘端,Drizzle 对其提供了专门的 drizzle-orm/d1 驱动支持。同时,数据库的迁移(Migration)通常交由 Cloudflare 的命令行工具 wrangler 来执行。

以下是完整的配置、开发及部署流程。


1. 准备工作与安装依赖

首先,在你的 Cloudflare Worker 或 Pages 项目中安装必要的依赖:

# 安装运行时依赖
npm install drizzle-orm

# 安装开发时依赖(用于生成迁移文件和配置)
npm install -D drizzle-kit wrangler

2. 配置文件

我们需要配置两个文件:一个是 Cloudflare 的 wrangler.toml(用于绑定 D1),另一个是 drizzle.config.ts(用于管理 Schema 和生成迁移文件)。

2.1 wrangler.toml (Cloudflare 配置)

首先,通过 Wrangler 创建一个 D1 数据库:

npx wrangler d1 create my-d1-db

创建成功后,控制台会输出对应的配置信息,将其复制并粘贴到你的 wrangler.toml 中:

#:schema node_modules/wrangler/config-schema.json
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[[d1_databases]]
binding = "DB" # 在 Worker 代码中访问数据库的变量名 (env.DB)
database_name = "my-d1-db"
database_id = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # 替换为实际的 ID
migrations_dir = "./drizzle" # 关键配置:指定 Wrangler 从哪里读取迁移 SQL 文件

2.2 drizzle.config.ts (Drizzle 配置)

在项目根目录下创建 drizzle.config.ts。由于 D1 底层是 SQLite,我们选择 sqlite 方言:

import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  dialect: 'sqlite', // D1 底层为 SQLite
  schema: './src/db/schema.ts', // 你的 schema 文件路径
  out: './drizzle', // 迁移文件输出目录(需与 wrangler.toml 中的 migrations_dir 一致)
});

3. 定义 Schema

创建 ./src/db/schema.ts,使用 Drizzle 的 SQLite 核心模块来定义表结构:

import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';

export const users = sqliteTable('users', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  email: text('email').unique().notNull(),
  createdAt: integer('created_at', { mode: 'timestamp' })
    .$defaultFn(() => new Date()),
});

4. 数据库迁移 (Generate & Migrate)

Drizzle 负责将 TypeScript Schema 转换为 SQL 语句(Generate),而 Wrangler 负责将这些 SQL 语句应用到本地开发环境或 Cloudflare D1 实体中(Migrate)。

步骤 A:生成迁移文件 (Generate)

运行以下命令,Drizzle-kit 会对比你的 Schema 并生成 SQL 变更文件至 ./drizzle 目录中:

npx drizzle-kit generate

运行后,你会看到 ./drizzle 目录下生成了类似 0000_xxxx.sql 的文件。

步骤 B:执行迁移 (Migrate)

使用 wrangler 运行迁移。

  • 本地开发环境迁移
    npx wrangler d1 migrations apply my-d1-db --local
  • 线上生产环境迁移
    npx wrangler d1 migrations apply my-d1-db --remote

5. 初始化 Drizzle 客户端

在 Worker 的入口文件中(通常是 src/index.ts),通过绑定注入的 env.DB 来初始化 Drizzle 客户端:

import { drizzle } from 'drizzle-orm/d1';
import * as schema from './db/schema';

export interface Env {
  DB: D1Database; // wrangler.toml 中绑定的 D1 数据库
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // 初始化 db 实例
    const db = drizzle(env.DB, { schema });

    // 后续可以在此处进行数据库操作...
    return new Response("OK");
  }
};

6. 数据的增删改查 (CRUD)

以下展示在 Worker 环境内,使用上面初始化的 db 实例进行常见数据操作:

import { drizzle } from 'drizzle-orm/d1';
import { eq } from 'drizzle-orm';
import * as schema from './db/schema';
import { users } from './db/schema';

export interface Env {
  DB: D1Database;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const db = drizzle(env.DB, { schema });

    // 1. 增 (Insert)
    const newUser = await db.insert(users).values({
      name: "张三",
      email: "zhangsan@example.com"
    }).returning(); // D1 支持 returning 子句返回插入的数据

    // 2. 查 (Select)
    // 查询所有数据
    const allUsers = await db.select().from(users);

    // 条件查询
    const singleUser = await db.select()
      .from(users)
      .where(eq(users.email, "zhangsan@example.com"))
      .get(); // .get() 返回单条数据,若无则返回 undefined

    // 3. 改 (Update)
    const updatedUser = await db.update(users)
      .set({ name: "张三丰" })
      .where(eq(users.id, 1))
      .returning();

    // 4. 删 (Delete)
    const deletedUser = await db.delete(users)
      .where(eq(users.id, 1))
      .returning();

    return Response.json({
      allUsers,
      singleUser
    });
  }
};

总结工作流:

  1. 修改 Schema:在 src/db/schema.ts 中增加或修改字段。
  2. 生成 SQL:运行 npx drizzle-kit generate
  3. 应用迁移
    • 本地测试:npx wrangler d1 migrations apply <db_name> --local
    • 线上部署:npx wrangler d1 migrations apply <db_name> --remote