Preamble
As I was grappling with this issue myself, I stumbled upon this question. While you may have already found the solution by now, I thought it would be helpful to share the approach I devised in case others find themselves in a similar situation in the future.
I chanced upon your GitHub discussion, which led me to another GitHub issue that ultimately guided me towards what I believe is a viable solution.
Problem Explanation
The challenge lies in explicitly handling a many-to-many relationship, where relations are managed through the creation/deletion of records within a separate relation table. This concept is elaborated in the Prisma documentation available here. The set
method does not generate or remove records; instead, it merely disconnects existing relationships and establishes connections between the specified models.
Solution
Since set
does not handle record creation or deletion, we need to address both of these tasks separately. Fortunately, both operations can be executed within a single query. Below is a modified version of your code reflecting my implementation:
// BEFORE -- NOT WORKING
update(id: string, updateProductDto: UpdateProductDto) {
const tags = updateProductDto.tags.map((tag) => ({
productId_tagId: {
productId: id,
tagId: tag.id,
},
}));
return this.prisma.product.update({
where: { id: id },
data: {
...updateProductDto,
tags: {
set: [...tags],
},
},
});
}
// AFTER -- WORKING
update(id: string, updateProductDto: UpdateProductDto) {
return this.prisma.product.update({
where: { id },
data: {
...updateProductDto,
tags: {
deleteMany: {},
create: updateProductDto.tags.map((t) => ({ tag: { connect: { t.id } } }))
},
},
});
}
Notes
There are a few considerations to keep in mind when employing this approach:
- This method completely resets the relationships between the two models, even if the new set of tags includes tags that were previously associated. Therefore, if there are additional properties in your relation table records that you wish to retain (e.g., the
createdAt
property), you must ensure they are transferred accordingly.
- I have only validated this approach using Prisma versions 4.1.0 and higher. I am uncertain about the version you were utilizing at that time or currently.
I trust that this information proves beneficial to anyone who comes across this post!