typescript - Prisma uppdatera eller skapa och radera gamla relationer
Jag har ett projekt som består av Posts och varje inlägg kan ha en samling av Tags. Jag försöker möjliggöra en redigeringsfunktion som tillåter att taggar för inlägg uppdateras/läggs till/tas bort. För närvarande gör min fråga en upsert av dessa taggar, men jag upplever vissa problem som orsakas av raderaspekten. Varje gång nya taggar skapas, eftersom de inte har någon ID vid det tillfället, tas de bort omedelbart.
await Prisma.post.update({
where: {
id: postId,
},
data: {
title,
content,
updatedAt: new Date(),
tags: {
// Upsert tags, remove tags that are not in the request
upsert: tags.map((tag) => ({
where: {
id: tag.id ? tag.id : "0",
},
create: {
name: tag.name,
color: tag.color,
creator: {
connect: {
id: session.user.id,
},
},
},
update: {
name: tag.name,
color: tag.color,
},
})),
deleteMany: {
id: {
notIn: tags.map((tag) => tag.id ?? "0"),
},
},
},
},
include: {
tags: true,
},
});
Jag har försökt olika lösningar såsom att använda namnet eller andra egenskaper (t.ex. namn OCH färg). Ingen av dessa verkar lösa problemet, eftersom de slutar med att duplicera taggar och orsaka liknande fel.
Här är schemat jag använder i mina Post- och Tag-modeller.
Postmodel Post {
id String @id @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
title String
content String
authorId String
author User @relation(fields: [authorId], references: [id])
comments Comment[]
tags Tag[]
}
Tagmodel Tag {
id String @id @default(uuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
name String
color String
creatorId String
creator User @relation(fields: [creatorId], references: [id])
posts Post[]
}
Om någon kunde visa mig rätt riktning för hur man hanterar en situation som denna, skulle jag vara mycket tacksam.
Svar #1
Du bör klippa ut dina steg i en transaktion för att ta bort taggar som inte finns i frågan innan du infogar de nya. Sedan kan du skapa och uppdatera dina data och returnera ditt inlägg
Med interaktiva transaktioner
I din schema.prisma bör du aktivera interactiveTransactions, för detta:
generator client {
provider = "prisma-client-js"
previewFeatures = ["interactiveTransactions"]
}
Skär sedan ut dina steg i en transaktion
// Remove <Post> if you aren't in typescript
await prisma.$transaction<Post>(async (trx) => {
const existingTags = tags.filter(({ id }) => id);
const newTags = tags.filter(({ id }) => !id);
await trx.tag.deleteMany({
where: {
id: {
notIn: existingTags.map(({ id }) => id),
},
},
});
// Update the existing tags
await Promise.all(
tags.map((tag) =>
trx.tag.update({
where: {
id: tag.id,
},
data: {
color: tag.color,
name: tag.name,
},
})
)
);
await trx.tag.createMany({
data: newTags.map((tag) => ({
...tag,
creator: {
connect: {
id: session.user.id,
},
},
})),
});
return trx.post.update({
where: {
id: postId,
},
data: {
title,
content,
updatedAt: new Date(),
},
include: {
tags: true,
},
});
});
