数据库
数据库概述
RavenSaaS 使用 drizzle-orm 支持多种类型数据库。
配置数据库
以 Supabase 数据库为例,在 RavenSaaS 配置数据库的流程为:
1. 创建数据库
登录 Supabase 控制台,创建数据库
2. 查看数据库连接信息
在 Supabase 控制台,进入你创建的数据库,点击上方的 Connect

在弹出来的框中复制数据库连接信息,类似这样的字符串:
1postgresql://postgres.vbpzjovjpcezduozlkkh:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true
[YOUR-PASSWORD] 需要替换成你在创建数据库时设置的密码。
3. 配置数据库
修改项目配置文件:.env.development 和 .env.production
设置数据库连接信息:
1DATABASE_URL="postgresql://postgres.vbpzjovjpcezduozlkkh:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
初始化数据库
在配置好 DATABASE_URL 后,在项目根目录下执行以下命令,初始化数据库:
1pnpm db:migrate
这个命令会执行 src/db/migrations 目录下的所有迁移文件,创建数据库表
注意:如果你通过 DATABASE_URL 配置的不是一个新创建的数据库,或者数据库之前已经存在 RavenSaaS 的库表信息,请不要执行以上命令。而是比较 src/db/migrations 目录下所有迁移文件的 sql 内容,手动执行 sql 语句,更新数据库表。
2. 修改数据库配置(默认不修改)
修改 ./drizzle.config.ts 文件,使用新的数据库连接配置。
默认是 Postgres 数据库连接配置,你可以参考 drizzle-orm 文档按需修改。
1import { defineConfig } from "drizzle-kit";
2import * as dotenv from "dotenv";
3
4dotenv.config({ path: '.env.development' });
5if (!process.env.DATABASE_URL) {
6 dotenv.config({ path: '.env' });
7}
8
9export default defineConfig({
10 schema: "./src/db/schema.ts",
11 out: "./src/db/migrations",
12 dialect: "postgresql",
13 dbCredentials: {
14 url: process.env.DATABASE_URL!,
15 },
16 verbose: true,
17 strict: true,
18});
19
3. 修改数据库连接实例(默认不修改)
根据你使用的数据库类型,修改数据库连接实例。
1import { drizzle } from "drizzle-orm/postgres-js";
2import postgres from "postgres";
3
4const isCloudflareWorker =
5 typeof globalThis !== "undefined" && "Cloudflare" in globalThis;
6
7// DB Instance
8let dbInstance: ReturnType<typeof drizzle> | null = null;
9
10export function db() {
11 const databaseUrl = process.env.DATABASE_URL;
12 if (!databaseUrl) {
13 throw new Error("DATABASE_URL is not set");
14 }
15
16 if (isCloudflareWorker) {
17 const client = postgres(databaseUrl, {
18 prepare: false,
19 max: 1,
20 idle_timeout: 10,
21 connect_timeout: 5,
22 });
23
24 return drizzle(client);
25 }
26
27 if (dbInstance) {
28 return dbInstance;
29 }
30
31 const client = postgres(databaseUrl, {
32 prepare: false,
33 max: 10,
34 idle_timeout: 30,
35 connect_timeout: 10,
36 });
37 dbInstance = drizzle({ client });
38
39 return dbInstance;
40}
更新数据库
4. 生成数据库迁移文件
如果在项目创建之后,你使用的是一个新的数据库,且是通过 pnpm db:migrate 命令初始化的数据库,如果后续你拉取了最新的代码,可以继续执行以下命令,更新数据库表
1pnpm db:generate
这个命令会根据 src/db/migrations 目录下所有迁移文件的 sql 内容,增量更新数据库表。
操作数据库
在 src/models 目录下,写数据库操作文件,实现对数据表的增删改查。可参考以下操作 posts 表的示例:
数据表操作语法可参考 drizzle-orm 文档。
创建数据
1export async function insertPost(
2 data: typeof posts.$inferInsert
3): Promise<typeof posts.$inferSelect | undefined> {
4 const [post] = await db().insert(posts).values(data).returning();
5
6 return post;
7}
更新数据
1export async function updatePost(
2 id: string,
3 data: Partial<typeof posts.$inferInsert>
4): Promise<typeof posts.$inferSelect | undefined> {
5 const [post] = await db()
6 .update(posts)
7 .set(data)
8 .where(eq(posts.id, parseInt(id)))
9 .returning();
10
11 return post;
12}
查询数据
1export async function getPostById(
2 id: string
3): Promise<typeof posts.$inferSelect | undefined> {
4 const [post] = await db()
5 .select()
6 .from(posts)
7 .where(eq(posts.id, parseInt(id)))
8 .limit(1);
9
10 return post;
11}
12
13export async function getPostBySlug(
14 slug: string
15): Promise<typeof posts.$inferSelect | undefined> {
16 const [post] = await db()
17 .select()
18 .from(posts)
19 .where(eq(posts.slug, slug))
20 .limit(1);
21
22 return post;
23}
24
25export async function getAllPosts(
26 page: number = 1,
27 limit: number = 10
28): Promise<(typeof posts.$inferSelect)[] | undefined> {
29 const offset = (page - 1) * limit;
30
31 const data = await db()
32 .select()
33 .from(posts)
34 .limit(limit)
35 .offset(offset)
36 .orderBy(desc(posts.created_at));
37
38 return data;
39}
使用其他类型数据库
如果你想使用其他类型的数据库,可以参考 drizzle-orm 官方文档进行配置。
参考
Last updated on 2025年1月5日