跳到主要内容

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 脚本,并使用以下命令启动它。


"prisma": {
"seed": "ts-node prisma/seed.ts"
},

信息

对于 TypeScript,ts-node 默认执行转译和类型检查;类型检查可以使用以下标志禁用 --transpile-only

示例:"seed": "ts-node --transpile-only prisma/seed.ts"

这对于减少内存使用 (RAM) 和提高 seed 脚本的执行速度非常有用。

与 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 devprisma migrate reset 而不进行 seeding 时,您可以传递 --skip-seed 标志。

示例 seed 脚本

在这里,我们为不同的情况提出了一些特定的 seed 脚本。您可以随意自定义这些脚本,也可以按此处所示使用它们

使用 TypeScript 或 JavaScript seed 您的数据库

  1. 创建一个名为 seed.ts 的新文件。这可以放置在您的项目文件夹结构中的任何位置。下面的示例将其放置在 /prisma 文件夹中。

  2. seed.ts 文件中,导入 Prisma Client,初始化它并创建一些记录。例如,采用以下带有 UserPost 模型的 Prisma schema

    schema.prisma
    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.ts 文件中创建一些新用户和帖子

    seed.ts
    import { 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)
    })
  3. 添加 typescriptts-node@types/node 开发依赖项

    npm install -D typescript ts-node @types/node
  1. 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"
    },
  2. 要 seed 数据库,请运行 db seed CLI 命令

    npx prisma db seed

通过原始 SQL 查询 seed 您的数据库

您还可以使用原始 SQL 查询来 seed 数据库中的数据。

虽然您可以使用纯文本 .sql 文件(例如数据转储)来执行此操作,但通常更容易将这些原始查询(如果它们的大小很小)放入 seed.js 文件中,因为它省去了您处理数据库连接字符串以及创建对 psql 等二进制文件的依赖的麻烦。

要将其他数据 seed 到上面的 schema.prisma 中,请将以下内容添加到 seed.js(或 seed.ts)文件中

seed.js
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 调用,例如对文件末尾的以下更改

seed.js
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 您的数据库。


以下示例在与 seed.sh 相同的文件夹中运行 Go 脚本


seed.sh
#!/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/

用户定义的参数

此功能从 4.15.0 及更高版本可用。

prisma db seed 允许您在 seed 文件中定义自定义参数,您可以将这些参数传递给 prisma db seed 命令。例如,您可以定义自己的参数来为不同环境 seed 不同的数据,或者在某些表中部分 seed 数据。

这是一个示例 seed 文件,它定义了一个自定义参数来为不同环境 seed 不同的数据

"seed.js"
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 数据库的其他工具的非详尽列表