I want to use Prisma to associate articles with tags, that is: A post has multiple tags and a tag belongs to multiple posts
But the example in Prisma will result in the creation of duplicate tags
Here is my Prisma model
model Article {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String
summary String
link String @unique
archive String
content String
image String
tags Tag[]
}
model Tag {
id Int @id @default(autoincrement())
name String
articles Article[]
}
This is my code according to the documentation, it causes duplicate tags to appear
await prisma.article.create({
data: {
title,
summary,
link,
archive,
content,
image,
tags: {
create: tags.map((tag) => ({ name: tag })),
},
},
});
When I use connectOrCreate, it reports an error in many-to-many mode
await prisma.article.create({
data: {
title,
summary,
link,
archive,
content,
image,
tags: {
connectOrCreate: {
where: tags.map((tag) => ({ name: tag })),
create: tags.map((tag) => ({ name: tag })),
},
},
},
});
There's two errors in the code.
Tag.name
field is not uniqueFrom what I can infer from your domain, two tags should not have the same name. Furthermore, since the name
field is not unique, you can't use it by itself to uniquely identify a specific Tag
record and so Prisma will complain if you try to pass only the name
field in the where
condition of connectOrCreate
.
The simplest and logical solution to this is to make the name
field unique. Here's your updated Tag model
model Tag {
id Int @id @default(autoincrement())
name String @unique // change
articles Article[]
}
connectOrCreate
You're passing separate arrays to the where
and create
fields. Instead, when you want to connect/create multiple records, pass an array of objects to connectOrCreate
each with its own where
and create
field. Here's an example from the Prisma Docs that shows how to use connectOrCreate with multiple records.
This is what your create query should look like:
await prisma.article.create({
data: {
title,
summary,
link,
archive,
content,
image,
tags: {
connectOrCreate: tags.map((tag) => {
return {
where: { name: tag },
create: { name: tag },
};
}),
},
},
});