Search code examples
prisma

How to update document with specific version


I have a use case where my function first gets a user record, does some work on it and then updates it. To guarantee correct operation, I need to ensure that user record was not updated while such work is being done. Typically, I would do this by adding version to my user model, thus I get current version and update based on this exact version (auto incrementing it with each update), however I am getting a strange uniqueness error that I am not able to figure out:

User model

model User {
  uid       String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  version   Int      @default(0)
  email     String   @unique
}

Update opperation

prisma.user.update({
  where: { uid, version },
  data: { ...newData, version: { increment: 1 } }
})

Version is highlighted with following error

Type '{ uid: string; version: number; }' is not assignable to type 'UserWhereUniqueInput'. Object literal may only specify known properties, and 'version' does not exist in type 'UserWhereUniqueInput'.ts(2322)


Solution

  • It's because you need a unique clause to use a where clause on a simple update. Prisma ask you to give it a unique contraint for this type of update, like for the where clause in a findUnique. Currently you unique constraint is on the email field

    Here you have 2 solutions

    The good practice?

    Add a unique constraint between uid and version

    model User {
      uid       String   @id @default(uuid())
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
      version   Int      @default(0)
      email     String   @unique
    
      // new unique constraint
      @@unique([uid, version])
    }
    

    and then you can do your update with the new unique constraint

    prisma.user.update({
      where: { uid_version: { uid, version } },
      data: { ...newData, version: { increment: 1 } }
    })
    

    Easy win

    If you want, you can also do an updateMany that will not need a unique constraint to filter

    prisma.user.updateMany({
      where: { uid, version },
      data: { ...newData, version: { increment: 1 } }
    })