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)
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 } }
})