How to use connectOrCreate with many to many in prisma

Viewed 3077

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 })), 
      },
    },
  },
});
1 Answers

There's two errors in the code.

Tag.name field is not unique

From 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[]
}

Incorrect syntax for 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 },
            };
        }),
    },
  },
});
Related