播种
本指南介绍如何使用 Prisma Client 和 Prisma ORM 集成的播种功能为您的数据库播种。播种使您可以一致地重新创建数据库中的相同数据,并且可用于
- 用应用程序启动所需的数据填充数据库,例如默认语言或货币。
- 提供基本数据以在开发环境中验证和使用您的应用程序。如果您使用 Prisma Migrate,这尤其有用,因为有时需要重置开发数据库。
如何在 Prisma ORM 中为数据库播种
Prisma ORM 的集成播种功能需要您在 package.json
文件的 "prisma"
键中的 "seed"
键中定义一个命令。这可以是任何命令,prisma db seed
将执行该命令。在本指南中,以及作为默认设置,我们建议在您的项目的 prisma/
文件夹中编写一个播种脚本,并以该命令开头。
- TypeScript
- JavaScript
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
使用 TypeScript 时,ts-node
默认执行转译和类型检查;可以使用以下标志 --transpile-only
禁用类型检查。
示例:"seed": "ts-node --transpile-only prisma/seed.ts"
这有助于减少内存使用量(RAM)并提高播种脚本的执行速度。
"prisma": {
"seed": "node prisma/seed.js"
},
与 Prisma Migrate 集成播种
使用 Prisma ORM 为数据库播种有两种方式:通过 prisma db seed
手动播种,以及通过 prisma migrate reset
(以及在某些情况下 prisma migrate dev
)自动播种。
使用 prisma db seed
,您决定何时调用播种命令。例如,这对于测试设置或准备新的开发环境很有用。
Prisma Migrate 还与您的种子无缝集成,前提是您遵循以下部分中的步骤。当 Prisma Migrate 重置开发数据库时,会自动触发播种。
在以下情况下,Prisma Migrate 会重置数据库并触发播种
- 您手动运行
prisma migrate reset
CLI 命令。 - 在使用
prisma migrate dev
的上下文中,交互式地重置数据库,例如,由于迁移历史冲突或数据库模式漂移。 prisma migrate dev
实际上创建了数据库,因为它之前不存在。
如果要在不进行播种的情况下使用 prisma migrate dev
或 prisma migrate reset
,您可以传递 --skip-seed
标志。
示例播种脚本
这里我们建议一些针对不同情况的特定播种脚本。您可以随意自定义这些脚本,但也可以按原样使用它们。
使用 TypeScript 或 JavaScript 为数据库播种
如果您使用的是带有 PostgreSQL、SQLite 或 MySQL 的 TypeScript,请参考:@snaplet/seed。
- TypeScript
- JavaScript
-
创建一个名为
seed.ts
的新文件。此文件可以放在项目文件夹结构中的任何位置。以下示例将它放在/prisma
文件夹中。 -
在
seed.ts
文件中,导入 Prisma Client,对其进行初始化,并创建一些记录。例如,以下 Prisma 模式包含User
和Post
模型schema.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 时,您需要像这样设置您的播种脚本
package.json"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
}, -
要为数据库播种,请运行
db seed
CLI 命令npx prisma db seed
-
创建一个名为
seed.js
的新文件。此文件可以放在项目文件夹结构中的任何位置。以下示例将它放在/prisma
文件夹中。 -
在
seed.js
文件中,导入 Prisma Client,对其进行初始化,并创建一些记录。例如,以下 Prisma 模式包含User
和Post
模型schema.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"
}
} -
要为数据库播种,请运行
db seed
CLI 命令npx prisma db seed
通过原始 SQL 查询为数据库播种
您还可以使用原始 SQL 查询来为数据库播种数据。
虽然您可以使用纯文本 .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 脚本)为数据库播种
除了 TypeScript 和 JavaScript,您还可以使用 Bash 脚本 (seed.sh
) 以其他语言(例如 Go 或纯 SQL)为数据库播种。
- 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
使用 @snaplet/seed
为数据库播种
@snaplet/seed
提供了一个工具包,旨在了解您的数据库模式,使您能够生成生产准确的数据并有效地为数据库播种。它利用了 TypeScript 的全部功能,为您提供类型安全且自动完成的体验来编写播种脚本。
@snaplet/seed
支持 PostgreSQL、SQLite 和 MySQL。
-
首先使用
npx prisma migrate dev
设置本地数据库。此示例将使用以下 Prisma 模式,其中包含User
和Post
模型schema.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
} -
执行
npx @snaplet/seed init prisma/seed
以在您的 Prisma 项目中初始化 Snaplet Seed。此命令会生成种子客户端并在prisma/seed/seed.ts
中创建一个示例种子文件。 -
在
prisma/seed/seed.ts
文件中使用生成的@snaplet/seed
客户端来创建您的种子。以下是如何通过修改最初生成的
prisma/seed/seed.ts
文件来创建新用户和帖子prisma/seed/seed.ts/**
* ! Executing this script will delete all data in your database and seed it with 10 users.
* ! Make sure to adjust the script to your needs.
* Use any TypeScript runner to run this script, for example: `npx tsx seed.ts`
* Learn more about the Seed Client by following our guide: https://docs.snaplet.dev/seed/getting-started
*/
import { createSeedClient } from "@snaplet/seed";
async function main() {
const seed = await createSeedClient();
// Truncate all tables in the database
await seed.$resetDatabase();
// Seed the database with 10 users
await seed.user((createMany) => createMany(10, {
// Create 10 posts for each of those users
posts: (createMany) => createMany(10),
}))
console.log("Database seeded successfully!");
process.exit();
};
main(); -
添加
tsx
(或任何其他 TypeScript 运行器)作为开发依赖项npm install -D tsx
-
将
prisma.seed
字段插入您的package.json
文件中,并配置命令来为数据库播种package.json{
"name": "my-project",
"version": "1.0.0",
"prisma": {
"seed": "tsx prisma/seed/seed.ts"
},
"devDependencies": {
"@types/node": "^14.14.21",
"tsx": "^4.7.2",
"typescript": "^4.1.3"
}
} -
要为数据库播种,请执行以下 CLI 命令
npx prisma db seed
-
要确保种子客户端与您的模式保持同步,请将
migrate
和postmigrate
脚本添加到 package.json 中package.json{
"name": "my-project",
"version": "1.0.0",
"prisma": {
"seed": "npx tsx prisma/seed/seed.ts"
},
"scripts": {
"migrate": "prisma migrate dev",
"postmigrate": "npx @snaplet/seed sync"
},
"devDependencies": {
"@types/node": "^14.14.21",
"tsx": "^4.7.2",
"typescript": "^4.1.3"
}
}
现在,您可以运行 npm run migrate
来代替 npx prisma migrate dev
,该命令还会在模式发生更改后同步种子客户端,并使您的数据库和种子客户端保持同步。
用户定义参数
此功能在 4.15.0 及更高版本中可用。
prisma db seed
允许您在种子文件中定义自定义参数,这些参数可以传递给 prisma db 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 集成的其他工具,以播种您的数据库