Docs/modules/数据库

数据库

NextShip 使用 PostgreSQL 和 Drizzle ORM 实现类型安全的数据库访问。

为什么选择 Drizzle?

  • 轻量级 - 不像 Prisma 那样需要 Rust 引擎
  • 类 SQL - 对 SQL 开发者来说语法熟悉
  • 类型安全 - 完整的 TypeScript 类型推断
  • 边缘就绪 - 可在 Serverless 环境中运行

配置

数据库客户端在 src/lib/db/index.ts 中配置:

import { drizzle } from "drizzle-orm/neon-http";
import { neon } from "@neondatabase/serverless";
 
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql);

定义表

表在 src/lib/db/schema.ts 中定义:

import { pgTable, text, timestamp, boolean } from "drizzle-orm/pg-core";
 
export const users = pgTable("users", {
  id: text("id").primaryKey(),
  email: text("email").notNull().unique(),
  name: text("name"),
  emailVerified: boolean("email_verified").default(false),
  image: text("image"),
  role: text("role", { enum: ["user", "admin"] }).default("user"),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});
 
export const posts = pgTable("posts", {
  id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
  title: text("title").notNull(),
  content: text("content"),
  authorId: text("author_id").references(() => users.id),
  published: boolean("published").default(false),
  createdAt: timestamp("created_at").defaultNow(),
});

查询

查询(Select)

// 获取所有用户
const allUsers = await db.select().from(users);
 
// 带条件查询
const admins = await db
  .select()
  .from(users)
  .where(eq(users.role, "admin"));
 
// 查询特定列
const emails = await db
  .select({ email: users.email })
  .from(users);

插入(Insert)

await db.insert(users).values({
  id: crypto.randomUUID(),
  email: "user@example.com",
  name: "John Doe",
});
 
// 批量插入
await db.insert(users).values([
  { id: "1", email: "a@example.com" },
  { id: "2", email: "b@example.com" },
]);

更新(Update)

await db
  .update(users)
  .set({ name: "Jane Doe" })
  .where(eq(users.id, userId));

删除(Delete)

await db
  .delete(users)
  .where(eq(users.id, userId));

连接查询(Joins)

const postsWithAuthors = await db
  .select({
    post: posts,
    author: users,
  })
  .from(posts)
  .leftJoin(users, eq(posts.authorId, users.id));

迁移

Push(开发环境)

直接将表结构更改推送到数据库:

pnpm db:push

生成迁移(生产环境)

# 生成迁移文件
pnpm db:generate
 
# 应用迁移
pnpm db:migrate

Drizzle Studio

可视化数据库浏览器:

pnpm db:studio

https://local.drizzle.studio 打开

Neon 分支

Neon 支持数据库分支用于开发:

  1. 在 Neon 控制台创建分支
  2. .env.local 中使用分支连接字符串
  3. 在合并前安全地测试更改

最佳实践

  • 使用 $defaultFn 自动生成 ID
  • 始终添加 createdAtupdatedAt 时间戳
  • 使用 references 定义外键
  • 按领域组织表结构文件