🫥
Prismaでリレーションも同時にcreateManyする
これ↓の詳細を適当に流し書き
(ツイートのコードは少し間違っています)
本題
以下のスキーマを定義しているときに、
model Hoge {
id Int @id @default(autoincrement())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
fugas Fuga[]
}
model Fuga {
id Int @id @default(autoincrement())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
hoge Hoge @relation(fields: [hogeId], references: [id])
hogeId Int
}
Hoge
と同時にFuga
も作りたい場合、通常create
ではこのような構文が使えます
import { prisma } from "@prisma/client" // みたいな想定
const hoge = await prisma.hoge.create({
data: {
name: "hoge1"
fugas: {
create: [
{ name: 'fuga1' },
{ name: 'fuga2' },
],
},
},
include: {
fugas: true, // 返り値にfugasを含める
},
})
しかし、createMany
の中ではcreateMany
を使えません。
古事記にもそう書いてあります。
なので、回避策を使う必要があります:
const hoges = await prisma.$transaction(
async tx =>
await Promise.all(
items.map(async ({ fugas, ...item}) =>
await tx.table1.create({
data: {
...item,
create: fugas, // Fuga[]
}
})
)
)
)
解説
await prisma.$transaction()
prismaのAPIで$transaction
という関数があります。これはユーザーがトランザクションを手動で定義したいときに使います
また、引数としてasync (tx: TransactionClient) => Promise<T>
をもつため、
await prisma.$transaction(async (tx) => await tx.hoge.create({ ...hoge }))
ができます。
また、配列を渡すことで複数のクエリを一つのトランザクションで実行することも可能です:
const [hoges, totalHoges] = await prisma.$transaction([
prisma.hoge.findMany({ where: { name: { contains: 'test' } } }),
prisma.hoge.count(),
])
Discussion
物騒な言葉が含まれていますね。。→ // 返り血にfugasを含める
ありがとうございます!修正しました😂