Chapter 02

schema.prisma 建模

掌握 datasource/generator 配置、model 定义、标量字段类型、字段与块级属性、枚举,写出干净的数据模型。

2.1 schema 文件三大块

一份 schema.prisma 由三类顶层块构成:datasource(连哪个库)、generator(生成什么)、model / enum(数据模型)。

datasource
声明数据源:provider(数据库类型)与 url(连接串,通常读 env)。一个 schema 只能有一个 datasource。
generator
声明要生成的产物。最常用 prisma-client-js(生成 JS/TS Client)。可配 output 自定义生成路径。
model
对应数据库一张表(MongoDB 是一个 collection),内含字段与属性。model 名默认映射为同名表,可用 @@map 改。
字段属性(field attribute)
单个 @ 前缀,作用于某个字段,如 @id@unique@default(...)@map(...)
块级属性(block attribute)
@@ 前缀,作用于整个 model,如 @@id([...]) 复合主键、@@unique([...])@@index([...])@@map(...)
枚举(enum)
顶层 enum 块定义一组固定取值,字段可用它做类型,映射到数据库原生 enum 或字符串约束。

2.2 标量字段类型

Prisma 类型TypeScriptPostgreSQL 默认
Stringstringtext
Intnumberinteger
BigIntbigintbigint
Floatnumberdouble precision
DecimalPrisma.Decimaldecimal(65,30)
Booleanbooleanboolean
DateTimeDatetimestamp(3)
JsonPrisma.JsonValuejsonb
BytesUint8Arraybytea

字段后加 ? 表示可空(对应 TS 的 | null),加 [] 表示数组(Postgres 原生数组或标量列表)。

2.3 常用字段属性

model User {
  id        Int      @id @default(autoincrement())
  uuid      String   @default(uuid())
  email     String   @unique
  name      String?                       // 可空
  role      String   @default("user")
  age       Int?     @db.SmallInt          // 原生类型修饰
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt            // 每次更新自动刷新
  legacyId  Int?     @map("legacy_id")       // 列名映射

  @@map("users")                            // 表名映射
}
@id
主键。配合 @default(autoincrement())(自增 Int)或 @default(cuid()) / @default(uuid())(字符串 ID)。
@default(...)
默认值:字面量、now()autoincrement()uuid()cuid()dbgenerated("...")(用数据库函数)。
@unique
唯一约束,使该字段可用于 findUnique
@updatedAt
特殊属性,Prisma 在每次 update 时自动写入当前时间。
@map / @@map
解耦"代码里的名字"与"数据库里的名字":@map 改列名,@@map 改表名。适配已有库或蛇形命名规范。
@db.类型
原生数据库类型修饰符,如 @db.VarChar(255)@db.SmallInt@db.Timestamptz,精确控制列类型。

2.4 枚举 enum

enum Role {
  USER
  EDITOR
  ADMIN
}

model User {
  id   Int    @id @default(autoincrement())
  role Role   @default(USER)
}

生成的 Client 中 Role 是 TS 枚举/联合类型,赋非法值编译期即报错。SQLite 不支持原生 enum,Prisma 会退化为带 check 约束的字符串。

2.5 复合主键与复合唯一

model Membership {
  userId  Int
  teamId  Int
  role    String @default("member")

  @@id([userId, teamId])              // 复合主键
}

model Post {
  slug    String
  locale  String
  title   String

  @@unique([slug, locale])            // 复合唯一
  @@index([locale])                   // 普通索引
}
@@unique / @@id 命名

复合唯一/主键在 Client 里生成组合字段名,如 slug_locale,用于 findUnique({ where: { slug_locale: { slug, locale } } })。可用 @@unique([...], name: "自定义名") 改。

2.6 Json 与标量列表字段

model Product {
  id       Int       @id @default(autoincrement())
  name     String
  tags     String[]                    // 标量数组(Postgres)
  metadata Json?                        // 任意 JSON(jsonb)
  price    Decimal   @db.Decimal(10, 2)  // 金额用 Decimal
}
金额别用 Float

浮点会丢精度。金额、汇率等用 Decimal + @db.Decimal(p, s),读出来是 Prisma.Decimal 对象,需 .toNumber() / .toFixed() 转换。

2.7 格式化与校验 schema

$ npx prisma format      # 自动对齐、排版 schema
$ npx prisma validate    # 校验 schema 语法与语义

推荐装官方 VS Code 插件 Prisma.prisma,获得语法高亮、自动补全、保存即 format、跳转定义。

2.8 小结与下一步