👻
prismaのseedを複数ファイルに分割する
はじめに
Prismaでは、下記のようにpackage.jsonにseedコマンドを設定することが出来ます。
package.json
"prisma": {
"seed": "ts-node prisma/seed.ts"
}
seedの実行はprisma db seedで手動で実行することができますが、prisma migrate devやprisma migrate resetを実行した時にも自動で実行されます。
多対多のリレーションを持つテーブルを作成
公式ドキュメントのprisma.schemaの定義をそのままコピーして、seedでデータを投入するテーブルを作成します。
prisma.schema
model Post {
id Int @id @default(autoincrement())
title String
categories CategoriesOnPosts[]
}
model Category {
id Int @id @default(autoincrement())
name String
posts CategoriesOnPosts[]
}
model CategoriesOnPosts {
post Post @relation(fields: [postId], references: [id])
postId Int // relation scalar field (used in the `@relation` attribute above)
category Category @relation(fields: [categoryId], references: [id])
categoryId Int // relation scalar field (used in the `@relation` attribute above)
assignedAt DateTime @default(now())
assignedBy String
@@id([postId, categoryId])
}
ディレクトリ構造
分割したseedを入れるためのフォルダとseedファイルを作成します。
start.tsがseedの起点となります。
tree prisma
prisma
├── migrations
├── schema.prisma
└── seed
├── category.ts
├── post.ts
└── start.ts
└── categories-on-posts.ts
package.jsonの設定
package.jsonにprismaのseedの設定を加えます。
package.json
"prisma": {
"seed": "ts-node ./prisma/seed/start.ts"
}
start.ts
start.tsは下記の通りです。
ESMで関数をimportしてawaitで非同期処理を順番に実行しています。
start.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
import { category } from './category';
import { post } from './post';
import { categoriesOnPosts } from './categories-on-posts';
async function main() {
await prisma.categoriesOnPosts.deleteMany();
await prisma.post.deleteMany();
await prisma.category.deleteMany();
await post();
await category();
await categoriesOnPosts();
}
main()
.catch((e) => console.error(e))
.finally(async () => {
await prisma.$disconnect();
});
seed
特に難しいところはありません。
post.ts
post.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export const post = async () => {
await prisma.post.createMany({
data: Array(60)
.fill(0)
.map((v, i) => ({
title: 'post' + i.toString(),
})),
});
};
category.ts
post.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export const category = async () => {
await prisma.category.createMany({
data: Array(60)
.fill(0)
.map((v, i) => ({
name: 'category' + i.toString(),
})),
});
};
categories-on-posts.ts
categories-on-posts.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export const categoriesOnPosts = async () => {
const posts = await prisma.post.findMany();
const categories = await prisma.category.findMany();
for (const post of posts) {
for (const category of categories) {
await prisma.categoriesOnPosts.create({
data: {
postId: post.id,
categoryId: category.id,
assignedBy: 'author',
},
});
}
}
};
まとめ
テーブル数が多くなってくると、1ファイルにseedを書くのが辛くなってくると思います。
また、1度の関数の実行で二つ以上のテーブルにデータを投入することもできますが、1ファイルで1つのテーブルのみにデータを投入するようにする事で、どのファイルがどのテーブルにデータを投入しているのか分かりやすくなり、seedを管理しやすくなります。
Discussion