Home > other >  Prisma 'set' with explicit many-to-many relation?
Prisma 'set' with explicit many-to-many relation?

Time:11-03

As in this document of Prisma, set can be used to override the value of a relation.

const user = await prisma.user.update({
  where: { email: '[email protected]' },
  data: {
    posts: {
      set: [{ id: 32 }, { id: 42 }],
    },
  },
})

But when I tried it with explicit many-to-many relation, it does not work.

model Product {
  id        String   @id @default(cuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  name        String
  description String?
  price       Decimal
  sku         String  @unique
  published   Boolean @default(false)

  tags ProductTag[]
}

model Tag {
  id   Int    @id @default(autoincrement())
  name String

  products ProductTag[]
}

model ProductTag {
  productId String
  tagId     Int

  createdAt DateTime @default(now())

  product Product @relation(fields: [productId], references: [id])
  tag     Tag     @relation(fields: [tagId], references: [id])

  @@id([productId, tagId])
}

My code to update Product

update(id: string, updateProductDto: UpdateProductDto) {
    const tags = updateProductDto.tags.map((tag) => ({
      productId_tagId: {
        productId: id,
        tagId: tag.id,
      },
    }));

    console.log(JSON.stringify(tags));

    return this.prisma.product.update({
      where: { id: id },
      data: {
        ...updateProductDto,
        tags: {
          set: [...tags],
        },
      },
    });
  }

I want to update the product's tag with the product's information.

How could I implement this correctly?

CodePudding user response:

I try a reply, but i would ask you to add the error messages, and your ProductTagWhereUniqueInput from node_modules/.prisma/client/index.d.ts

update(id: string, updateProductDto: UpdateProductDto) {
    const tags = updateProductDto.tags.map((tag) => ({
        // no need to encapsulate  
        productId: id,
        tagId: tag.id,
    }));
     // prevent the tags property to be update in product table, because you want to use set. 
    delete updateProductDto.tags;

    console.log(JSON.stringify(tags));

    return this.prisma.product.update({
      where: { id: id },
      data: {
        ...updateProductDto,
        tags: {
          set: tags, // no need to rebuild the array
        },
      },
    });
  }

CodePudding user response:

You could delete existing productTag records and then create new ones, in two separate queries. Then you could run the two queries as a transaction.

This is what it would look like

    // do other updates to Tags with values from updateProductDto. 

    const deleteOldtags = prisma.productTag.deleteMany({
        where: { productId: "__PRODUCT_ID__" },
    });

    const addNewTags = prisma.productTag.createMany({
        data: [
            {
                productId: "__PRODUCT_ID__",
                tagId: TAG_ID_VALUE

            },
            // ...array of productID and tagId objects. 
        ]
    })

    let updateTags = await prisma.$transaction([deleteOldtags, addNewTags])

This is a workaround, that is slightly different from set as it will create new records every time.

  • Related