Logo
RavenSaaS Docs

数据库

数据库概述

RavenSaaS 使用 drizzle-orm 支持多种类型数据库。

配置数据库

以 Supabase 数据库为例,在 RavenSaaS 配置数据库的流程为:

1. 创建数据库

登录 Supabase 控制台,创建数据库

2. 查看数据库连接信息

在 Supabase 控制台,进入你创建的数据库,点击上方的 Connect

Supabase Connect

在弹出来的框中复制数据库连接信息,类似这样的字符串:

Terminal
1postgresql://postgres.vbpzjovjpcezduozlkkh:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true

[YOUR-PASSWORD] 需要替换成你在创建数据库时设置的密码。

3. 配置数据库

修改项目配置文件:.env.development 和 .env.production

设置数据库连接信息:

Terminal
1DATABASE_URL="postgresql://postgres.vbpzjovjpcezduozlkkh:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true"

初始化数据库

在配置好 DATABASE_URL 后,在项目根目录下执行以下命令,初始化数据库:

Terminal
1pnpm db:migrate

这个命令会执行 src/db/migrations 目录下的所有迁移文件,创建数据库表

注意:如果你通过 DATABASE_URL 配置的不是一个新创建的数据库,或者数据库之前已经存在 RavenSaaS 的库表信息,请不要执行以上命令。而是比较 src/db/migrations 目录下所有迁移文件的 sql 内容,手动执行 sql 语句,更新数据库表。

2. 修改数据库配置(默认不修改)

修改 ./drizzle.config.ts 文件,使用新的数据库连接配置。

默认是 Postgres 数据库连接配置,你可以参考 drizzle-orm 文档按需修改。

./drizzle.config.ts
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. 修改数据库连接实例(默认不修改)

根据你使用的数据库类型,修改数据库连接实例。

Terminal
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 命令初始化的数据库,如果后续你拉取了最新的代码,可以继续执行以下命令,更新数据库表

Terminal
1pnpm db:generate

这个命令会根据 src/db/migrations 目录下所有迁移文件的 sql 内容,增量更新数据库表。

操作数据库

在 src/models 目录下,写数据库操作文件,实现对数据表的增删改查。可参考以下操作 posts 表的示例:

数据表操作语法可参考 drizzle-orm 文档。

创建数据

./src/models/posts.ts
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}

更新数据

./src/models/posts.ts
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}

查询数据

./src/models/posts.ts
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 官方文档进行配置。

参考

drizzle-orm

drizzle-orm 官方文档

查看文档

supabase

supabase 官方文档

查看文档

Last updated on 2025年1月5日