Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prisma many-to-many relations: create and connect

In my Prisma schema, I have a many-to-many relationship between posts and categories. I've added @map options to match the Postgres snake_case naming convention:

model Post {
  id         Int            @id @default(autoincrement())
  title      String
  body       String?
  categories PostCategory[]

  @@map("post")
}

model Category {
  id    Int            @id @default(autoincrement())
  name  String
  posts PostCategory[]

  @@map("category")
}

model PostCategory {
  categoryId Int      @map("category_id")
  postId     Int      @map("post_id")
  category   Category @relation(fields: [categoryId], references: [id])
  post       Post     @relation(fields: [postId], references: [id])

  @@id([categoryId, postId])
  @@map("post_category")
}

I'm trying to create a post with multiple categories at the same time. If a category exists, I'd like to connect the category to the post. If the category doesn't exist, I'd like to create it. The creation part is working well, but the connection part is problematic:

  await prisma.post.create({
    data: {
      title: 'Hello',
      categories: {
        create: [{ category: { create: { name: 'News' } } }],
        connect: {
          categoryId_postId: { categoryId: 1, postId: ? }, // This doesn't work, even if I had the postId
        },
      },
    },
  });

How can I connect an existing category to a new post with the schema that I have?

like image 833
Johnny Oshika Avatar asked Jan 29 '21 07:01

Johnny Oshika


People also ask

What is a relation in Prisma?

Hi friends, In this post, you’ll learn… | by Gnanabillian | YavarTechWorks | Aug, 2022 | Medium Hi friends, In this post, you’ll learn about Prisma relation A relation is a connection between two models in the Prisma schema.

What is a many-to-many relationship in SQL?

A "many-to-many" relationship has to be represented in a dedicated table, often called a junction or bridge table, among other names. The junction table maintains foreign keys to each table it mediates, making it the "many" side of its relationships to those tables.

What is a many-to-many library relationship?

Structurally, this is nearly identical to the case of a single library having many patrons, who themselves may borrow from multiple libraries. A "many-to-many" relationship has to be represented in a dedicated table, often called a junction or bridge table, among other names.


Video Answer


2 Answers

What you need here is connectOrCreate.

So something like this should work:

      await prisma.post.create({
        data: {
          title: 'Hello',
          categories: {
            create: [
              {
                category: {
                  create: {
                    name: 'category-1',
                  },
                },
              },
              { category: { connect: { id: 10 } } },
            ],
          },
        },
      });

You can also read more about this in the docs here

like image 130
Ryan Avatar answered Oct 12 '22 15:10

Ryan


This problem drove me up the wall so I'll contribute my solution here incase it helps someone else. First, read this: https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations

My schema is similar to the one in question, only difference is I have Files instead of Posts and Tags instead of Categories. To link the created file's tags to existing tags I used this:

  await Promise.all(DEFAULT_FILES[2].map(file => prisma.file.create({
    data: {
      ...file,
      user_id: userId,
      parent_id: homeFolder.id,
      tags: {
        create: file.tags?.map(name => ({
          tag: {
            connect: {
              id: tags.find(t => t.name === name)?.id
            }
          }
        }))
      },
    }
  })))
like image 33
TeemuK Avatar answered Oct 12 '22 13:10

TeemuK