Seeding
本指南介绍了如何使用 Prisma Client 和 Prisma ORM 的集成 seeding 功能来 seed 你的数据库。Seeding 允许你一致地在你的数据库中重新创建相同的数据,并且可以用于
- 用你的应用程序启动所需的数据填充你的数据库,例如默认语言或货币。
- 为在开发环境中验证和使用你的应用程序提供基本数据。 如果你正在使用 Prisma Migrate,有时需要重置你的开发数据库,这尤其有用。
如何在 Prisma ORM 中 seed 你的数据库
Prisma ORM 的集成 seeding 功能期望在你的 package.json
文件的 "prisma"
键中的 "seed"
键中有一个命令。 这可以是任何命令,prisma db seed
只会执行它。 在本指南中,作为默认设置,我们建议在你的项目的 prisma/
文件夹中编写一个 seed 脚本,并使用该命令启动它。
- TypeScript
- JavaScript
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
对于 TypeScript, ts-node
默认进行转译和类型检查; 可以使用以下标志 --transpile-only
禁用类型检查。
示例:"seed": "ts-node --transpile-only prisma/seed.ts"
这有助于减少内存使用 (RAM) 并提高 seed 脚本的执行速度。
"prisma": {
"seed": "node prisma/seed.js"
},
与 Prisma Migrate 集成 seeding
使用 Prisma ORM 进行数据库 seeding 有两种方式:手动使用 prisma db seed
,以及在 prisma migrate reset
和(在某些情况下)prisma migrate dev
中自动进行。
使用 prisma db seed
,你 决定何时调用 seed 命令。 例如,它对于测试设置或准备新的开发环境很有用。
假设你遵循以下部分中的步骤,Prisma Migrate 还可以与你的 seeds 无缝集成。 当 Prisma Migrate 重置开发数据库时,会自动触发 Seeding。
Prisma Migrate 在以下情况下重置数据库并触发 seeding
- 你手动运行
prisma migrate reset
CLI 命令。 - 在使用
prisma migrate dev
的上下文中交互式重置数据库 - 例如,由于迁移历史冲突或数据库 schema 漂移。 - 数据库实际上由
prisma migrate dev
创建,因为它之前不存在。
当你想在不 seeding 的情况下使用 prisma migrate dev
或 prisma migrate reset
时,你可以传递 --skip-seed
标志。
示例 seed 脚本
在这里,我们为不同的情况提供了一些具体的 seed 脚本。 你可以自由地以任何方式自定义这些脚本,但也可以按此处提供的原样使用它们
使用 TypeScript 或 JavaScript seed 你的数据库
- TypeScript
- JavaScript
-
创建一个名为
seed.ts
的新文件。 这可以放置在你的项目的文件夹结构中的任何位置。 以下示例将其放置在/prisma
文件夹中。 -
在
seed.ts
文件中,导入 Prisma Client,初始化它并创建一些记录。 例如,采用以下带有User
和Post
模型的 Prisma schemaschema.prismamodel User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String
published Boolean
user User @relation(fields: [userId], references: [id])
userId Int
}在你的
seed.ts
文件中创建一些新用户和帖子seed.tsimport { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
const alice = await prisma.user.upsert({
where: { email: '[email protected]' },
update: {},
create: {
email: '[email protected]',
name: 'Alice',
posts: {
create: {
title: 'Check out Prisma with Next.js',
content: 'https://prisma.org.cn/nextjs',
published: true,
},
},
},
})
const bob = await prisma.user.upsert({
where: { email: '[email protected]' },
update: {},
create: {
email: '[email protected]',
name: 'Bob',
posts: {
create: [
{
title: 'Follow Prisma on Twitter',
content: 'https://twitter.com/prisma',
published: true,
},
{
title: 'Follow Nexus on Twitter',
content: 'https://twitter.com/nexusgql',
published: true,
},
],
},
},
})
console.log({ alice, bob })
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
}) -
添加
typescript
、ts-node
和@types/node
开发依赖项npm install -D typescript ts-node @types/node
-
将
prisma.seed
字段添加到你的package.json
文件package.json{
"name": "my-project",
"version": "1.0.0",
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
"devDependencies": {
"@types/node": "^14.14.21",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
}
}某些项目可能需要你添加编译选项。 例如,当使用 Next.js 时,你将像这样设置你的 seed 脚本
package.json"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
}, -
要 seed 数据库,请运行
db seed
CLI 命令npx prisma db seed
-
创建一个名为
seed.js
的新文件。 这可以放置在你的项目的文件夹结构中的任何位置。 以下示例将其放置在/prisma
文件夹中。 -
在
seed.js
文件中,导入 Prisma Client,初始化它并创建一些记录。 例如,采用以下带有User
和Post
模型的 Prisma schemaschema.prismagenerator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String
published Boolean
user User @relation(fields: [userId], references: [id])
userId Int
}在你的
seed.js
文件中创建一些新用户和帖子seed.jsconst { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()
async function main() {
const alice = await prisma.user.upsert({
where: { email: '[email protected]' },
update: {},
create: {
email: '[email protected]',
name: 'Alice',
posts: {
create: {
title: 'Check out Prisma with Next.js',
content: 'https://prisma.org.cn/nextjs',
published: true,
},
},
},
})
const bob = await prisma.user.upsert({
where: { email: '[email protected]' },
update: {},
create: {
email: '[email protected]',
name: 'Bob',
posts: {
create: [
{
title: 'Follow Prisma on Twitter',
content: 'https://twitter.com/prisma',
published: true,
},
{
title: 'Follow Nexus on Twitter',
content: 'https://twitter.com/nexusgql',
published: true,
},
],
},
},
})
console.log({ alice, bob })
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
}) -
将
prisma.seed
添加到你的package.json
文件package.json{
"name": "my-project",
"version": "1.0.0",
"prisma": {
"seed": "node prisma/seed.js"
}
} -
要 seed 数据库,请运行
db seed
CLI 命令npx prisma db seed
通过原始 SQL 查询 seed 你的数据库
你还可以使用原始 SQL 查询来 seed 带有数据的数据库。
虽然你可以为此使用纯文本 .sql
文件(例如数据转储),但通常更容易将这些原始查询(如果它们很短)放入 seed.js
文件中,因为它省去了你处理数据库连接字符串并创建对 psql
等二进制文件的依赖项的麻烦。
要向上面的 schema.prisma
添加额外的数据,请将以下内容添加到 seed.js
(或 seed.ts
) 文件
async function rawSql() {
const result = await prisma.$executeRaw`INSERT INTO "User" ("id", "email", "name") VALUES (3, '[email protected]', 'Foo') ON CONFLICT DO NOTHING;`
console.log({ result })
}
并将此函数链接到 promise 调用,例如对文件末尾的以下更改
main()
.then(rawSql)
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
通过任何语言(使用 Bash 脚本)seed 你的数据库
除了 TypeScript 和 JavaScript,你还可以使用 Bash 脚本 (seed.sh
) 以另一种语言(如 Go 或纯 SQL)来 seed 你的数据库。
- Go
- SQL
以下示例在与 seed.sh
相同的文件夹中运行 Go 脚本
#!/bin/sh
# -e Exit immediately when a command returns a non-zero status.
# -x Print commands before they are executed
set -ex
# Seeding command
go run ./seed/
以下示例使用 psql 在与 seed.sh
相同的文件夹中运行 SQL 脚本
#!/bin/sh
# -e Exit immediately when a command returns a non-zero status.
# -x Print commands before they are executed
set -ex
# Seeding command
psql file.sql
用户定义的参数
此功能从 4.15.0 及更高版本可用。
prisma db seed
允许你在你的 seed 文件中定义自定义参数,你可以将这些参数传递给 prisma db seed
命令。 例如,你可以定义自己的参数,以便为不同的环境 seed 不同的数据,或者在某些表中部分 seed 数据。
这是一个示例 seed 文件,它定义了一个自定义参数,用于在不同环境中 seed 不同的数据
import { parseArgs } from 'node:util'
const options = {
environment: { type: 'string' },
}
async function main() {
const {
values: { environment },
} = parseArgs({ options })
switch (environment) {
case 'development':
/** data for your development */
break
case 'test':
/** data for your test environment */
break
default:
break
}
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
然后,你可以通过添加一个 分隔符 — --
—,后跟你的自定义参数,在使用 prisma db seed
时提供 environment
参数
npx prisma db seed -- --environment development
更进一步
这里列出了一些您可以在开发工作流程中与 Prisma ORM 集成以初始化数据库的其他工具(并非详尽列表)