如何删除显式多对多关系中的记录和任何关系记录?

How to delete a record and any relationship records in an explicit many to many relationship?

我正在努力寻找在 Prisma 中处理显式多对多关系的文档。所以我求助于 Whosebug 的开发....

我有一个多对多的关系:

model Fight {
  id            Int     @id @default(autoincrement())
  name          String
  fighters      FighterFights[]
}

model Fighter {
  id        Int     @id @default(autoincrement())
  name      String  @unique
  fights    FighterFights[]
}

model FighterFights {
  fighter      Fighter  @relation(fields: [fighterId], references: [id])
  fighterId    Int
  fight        Fight    @relation(fields: [fightId], references: [id])
  fightId      Int

  @@id([fighterId, fightId])
}

我正在尝试删除战斗并删除 FighterFights 中的关系,但不删除实际的战士。

我尝试了以下方法:

const result = await prisma.fight.delete({
  where: {
    id: Number(id),
  },
})

但出现错误:

PrismaClientKnownRequestError:
Invalid `prisma.fight.delete()` invocation:
Foreign key constraint failed on the field: `FighterFights_fightId_fkey (index)`

然后我也试了:

const result = await prisma.fight.delete({
  where: { id: Number(id) },
  data: {
    fighterFights: {
      deleteMany: {
        where: { fightId: id },
      },
    },
  },
})

但我得到错误:

PrismaClientValidationError:
Invalid `prisma.fight.delete()` invocation:

{
  where: {
    id: 1
  },
  data: {
  ~~~~
    fighterFights: {
      deleteMany: {
        where: {
          fightId: '1'
        }
      }
    }
  }
}

Unknown arg `data` in data for type Fight. Available args:

type deleteOneFight {
  where: FightWhereUniqueInput
}

我也试过:

const result = await prisma.fight.delete({
  where: {
    id: Number(id),
  },
  data: {
    fighterFights: {
      deleteMany: [{ fightId: { equals: Number(id) } }],
    },
  },
})

但出现错误:

Invalid `prisma.fight.delete()` invocation:

{
  where: {
    id: 1
  },
  data: {
  ~~~~
    fighterFights: {
      deleteMany: [
        {
          fightId: {
            equals: 1
          }
        }
      ]
    }
  }
}

Unknown arg `data` in data for type Fight. Available args:

type deleteOneFight {
  where: FightWhereUniqueInput
}

给你一个方法来做到这一点:

const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()

const saveData = async () => {
  const fighter1 = await prisma.fighter.create({
    data: {
      name: 'Ryu',
    },
  })
  const fighter2 = await prisma.fighter.create({
    data: {
      name: 'Ken',
    },
  })
  console.log('FIGHTERS');
  console.log(JSON.stringify(fighter1, null, 2));
  console.log(JSON.stringify(fighter2, null, 2));

  const fight = await prisma.fight.create({
    data: {
      name: 'Ryu vs Ken',
      fighters: {
        createMany: {
          data: [
            {
              fighterId: fighter1.id,
            },
            {
              fighterId: fighter2.id,
            },
          ]
        },
      },
    },
    select: {
      id: true,
      fighters: {
        select: {
          fighter: true,
        },
      },
    },
  });
  console.log('FIGHTS');
  console.log(JSON.stringify(await prisma.fight.findMany({ include: { fighters: true } }), null, 2));

  const fighterFightsToDelete = prisma.fighterFights.deleteMany({
    where: {
      fightId: fight.id,
    }
  })

  const fightToDelete = prisma.fight.delete({
    where: {
      id: fight.id,
    }
  })

  await prisma.$transaction([ fighterFightsToDelete, fightToDelete ])
  console.log('RESULT');
  console.log(JSON.stringify(await prisma.fight.findMany({ include: { fighters: true } }), null, 2));
  console.log(JSON.stringify(await prisma.fighter.findMany({ include: { fights: true } }), null, 2));
}

saveData()

结果如下:)