🫥

Prismaでリレーションも同時にcreateManyする

2023/02/16に公開
2

これ↓の詳細を適当に流し書き

(ツイートのコードは少し間違っています)
https://twitter.com/RikuS3n/status/1626086830545473536?s=20&t=E18UlZBQlu47Z0S8s1iYoA

本題

以下のスキーマを定義しているときに、

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を含める

import { prisma } from "@prisma/client" // みたいな想定

const hoge = await prisma.hoge.create({
  data: {
    name: "hoge1"
    fugas: {
      create: [
        { name: 'fuga1' },
        { name: 'fuga2' },
      ],
    },
  },
  include: {
    fugas: true, // 返り血にfugasを含める
  },
})