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
数据库 seeding 在 Prisma ORM 中以两种方式发生:手动使用 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
创建的,因为它之前不存在。
当您想要使用 prisma migrate dev
或 prisma migrate reset
而不进行 seeding 时,您可以传递 --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
等二进制文件的依赖的麻烦。
要将其他数据 seed 到上面的 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 集成在开发工作流程中以 seed 数据库的其他工具的非详尽列表