Richard
03/29/2022, 3:49 PMconnectOrCreate
and disconnect
in a single query when updating many:many relations?Richard
03/29/2022, 3:49 PMawait prisma.article.update({
where: { name: 'something' },
data: {
tags: {
disconnect: [{ name: 'b' }],
connectOrCreate: {
create: { name: 'c' },
where: { name: 'c' },
},
},
},
})
Unfortunately, this examples expects me to previously understand which posts I want to disconnect
and which I want to connectOrCreate
— so I gather it’s not possible to do this in a single query via prisma?
--
Example
Schema:
model Article {
id String @id @db.VarChar
author String @db.VarChar
posts ArticleToPost[]
}
model Post {
id String @id @db.VarChar
name String @db.VarChar @unique
articles ArticleToPost[]
}
model ArticleToPost{
id Int @id @default(autoincrement())
articleId String @db.VarChar
postId String @db.VarChar
post Post @relation(fields: [postId], references [id])
article Article @relation(fields: [articleId], references [id])
}
Input:
{
articleId: 1,
posts: [
{name: "What a post"},
{name: "Another post"},
{name: "Interesting post"}
]
}
Expected behaviour:
connectOrCreate
• If a post with the name doesn’t exist create
post & connect
to article
• If a post with the name exists, connect
to article
disconnect
• If an article previously had other posts connected, disconnect
Expected result:
article.posts WHERE articleId = 1
returns
// same as input but now I have the postId as well
[
{id: 1, name: "What a post"},
{id: 2, name: "Another post"},
{id: 3, name: "Interesting post"}
]
Richard
03/29/2022, 3:53 PMNurul
03/30/2022, 11:14 AMconst user = await prisma.user.update({
where: { email: '<mailto:alice@prisma.io|alice@prisma.io>' },
data: {
posts: {
set: [{ id: 32 }, { id: 42 }],
},
},
})
In the above example, we update an existing User record by disconnecting any previous Post records and connecting two other existing ones.Richard
03/31/2022, 4:01 PMset
relates to my thoughts about how I wanted to determine `disconnection`/`createOrConnect` : disconnect the (mathematical) set difference and the createOrConnect the new set)Richard
03/31/2022, 4:05 PMRichard
03/31/2022, 5:52 PMcreatePosts
& existingPosts
2. Create missing posts
3. update relation (set […createdPosts, existingPosts]
)
This looks much better now:
// 1. Partition input
const [createPosts, existingPosts] = data.reduce(...)
// 2. create missing posts
const created = await ctx.prisma.$transaction(
createPosts.map((createPost) =>
ctx.prisma.article.create({ data: createPost, select: { id: true } }),
),
);
// 3. set relations
const updated = await ctx.prisma.article.update({
where: { id: programId },
data: {
applySteps: {
set: [...created, ...existingPosts],
},
},
});
The only bummer here is that I have to wrap the post creation in a transaction because the findMany
doesn’t return the id that I later need.
But you solved my use case. Thanks a lot @Nurul 🙏Nurul
04/01/2022, 9:17 AM