Prisma: Model with three unique index fields referencing optional fields - prisma

I got a question regarding unique indexes with optional values.
I have a schema like this:
model Thread {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
body String
user User #relation(fields: [userId], references: [id])
userId Int
likes Like[] #relation("ThreadsOnLikes")
}
model Like {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
user User #relation(fields: [userId], references: [id])
userId Int
thread Thread? #relation("ThreadsOnLikes", fields: [threadId], references: [id])
threadId Int?
comment Comment? #relation("CommentsOnLikes", fields: [commentId], references: [id])
commentId Int?
##unique([userId, threadId, commentId])
}
And inside a resolver I want to for example delete a like from a user for a specific threadId like so:
await db.thread.update({
where: { id: input.id },
data: {
likes: {
delete: {
userId_threadId_commentId: { userId: session.userId, threadId: input.id },
},
}
}
})
But when I try to execute that mutation, prisma throws the following error:
Argument commentId for data.likes.delete.userId_threadId_commentId.commentId is missing.
When I add it to the delete argument with , commentId: null it states this error:
Argument commentId: Got invalid value null on prisma.updateOneThread. Provided null, expected Int.
Although inside the database the comment_id field is actually null . Is this a bug or how is this fixable?

From the docs:
All fields that make up the unique constraint must be mandatory fields. The following model is not valid because id could be null:
model User {
firstname Int
lastname Int
id Int?
##unique([firstname, lastname, id])
}
The reason for this behavior is that all connectors consider null values to be distinct, which means that two rows that look identical are considered unique:
firstname | lastname | id
-----------+----------+------
John | Smith | null
John | Smith | null
I am not sure why Prisma is unable to validate schema beforehand in "compile time", maybe it is a bug, so I suggest you to maybe create an issue on Github?

Related

Prisma update query only allowing an update by the ID field and not anything else

const response = await prisma.teamMember.update({
where: {
teamId,
userId: memberToEditId,
},
data: {
role,
},
});
Argument where of type TeamMemberWhereUniqueInput needs exactly one argument, but you provided teamId and userId. Please choose one. Available args:
type TeamMemberWhereUniqueInput {
id?: String
}
Unknown arg `teamId` in where.teamId for type TeamMemberWhereUniqueInput. Did you mean `id`? Available args:
type TeamMemberWhereUniqueInput {
id?: String
}
Unknown arg `userId` in where.userId for type TeamMemberWhereUniqueInput. Did you mean `id`? Available args:
type TeamMemberWhereUniqueInput {
id?: String
}
Hey guys. I'm trying to update a specific document based off of a specific value(s) in my table, but it only seems to let me use the primary key for the table? My schema looks like:
model TeamMember {
id String #id #default(cuid())
teamId String
userId String
role Role #default(MEMBER)
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
team Team #relation(fields: [teamId], references: [id], onDelete: Cascade)
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
}
model Team {
id String #id #default(cuid())
name String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
TeamMember TeamMember[]
}
model User {
id String #id #default(cuid())
name String?
email String? #unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
TeamMember TeamMember[]
theme Theme #default(LIGHT)
}
To fix this, temporarliy I can make a separate findFirst query, and use the returned row to get the ID of the row which i want to update. This is fine, however I know it can be done without doing this, and it is a little ugly having two queries when one can work just fine.
Any help would be greatly appreciated.
Prisma needs to uniquely identify a single record which needs to be updated, due to which the whereUnique constraint is enforced.
For now, you can use updateMany as a workaround for this, this unique constraint is not enforced for updateMany

prisma nested writes throw unknown args

I have the shorten schema like that:
model PATIENT {
patient_id Int #id #default(autoincrement())
patient_name String
patient_identity_card BigInt #unique
password String
wallet_id Int?
birthday DateTime
address String
status_id Int
gender String #default("Nam")
phone String #default("0935438280")
current_treatment_place_id Int
avatar_url String?
treatment_place TREATMENT_PLACE #relation(fields: [current_treatment_place_id], references: [place_id])
status PATIENT_STATUS #relation(fields: [status_id], references: [status_id])
card CART?
patient_passive_contact PATIENT_CONTACT[] #relation("ActiveContact_referredToPatient")
patient_active_contact PATIENT_CONTACT[] #relation("PassiveContact_referredToPatient")
BE_MANAGED_HISTORY BE_MANAGED_HISTORY[]
}
model BE_MANAGED_HISTORY {
place_id Int
patient_id Int
time DateTime
status_id Int
status PATIENT_STATUS #relation(fields: [status_id], references: [status_id])
patient PATIENT #relation(fields: [patient_id], references: [patient_id])
place TREATMENT_PLACE #relation(fields: [place_id], references: [place_id])
change_type_id Int
change_type CHANGE_MANAGED_HISTORY_TYPE #relation(fields: [change_type_id], references: [type_id])
##id([place_id, patient_id, time])
}
I want to create a BE_MANAGED_HISTORY record and through it create a PATIENT record with needed information. The nested writes below:
const res = await prisma.BE_MANAGED_HISTORY.create({
data: {
place_id: treatmentPlaceId,
time: new Date(startDate),
status_id: patientStatus,
change_type_id: 1,
patient: {
create: {
patient_name: patientName,
gender,
birthday: new Date(birthday),
patient_identity_card: identity,
password: hashedPassword,
phone,
address,
status_id: patientStatus,
current_treatment_place_id: treatmentPlaceId,
avatar_url: avatarUrl,
}
}
},
})
But prisma throws an error:
Unknown arg patient in data.patient for type BE_MANAGED_HISTORYUncheckedCreateInput. Did you mean patient_id?
Argument patient_id for data.patient_id is missing.
So can I create an beManagedHistory and create an patient inside nested writes?
We have to create a PATIENT record first, and nested in it creating a BE_MANAGED_HISTORY record.

How Do I Resolve This Prisma relationship schema error

model Match {
id String #id #unique #default(cuid())
name String
description String
player1 User #relation( fields: [player1Id], references: [id])
player1Id String
player2 User #relation( fields: [player2Id], references: [id])
player2Id String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
leagueId String
}
model User {
id String #id #unique #default(uuid())
email String #unique
password String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
matches Match[]
}
Getting following error
Error: Schema parsing
error: Error validating model "Match": Ambiguous relation detected. The fields `player1` and `player2` in model `Match` both refer to `User`. Please provide different relation names for them by adding `#relation(<name>).
--> schema.prisma:85
|
84 | description String
85 | player1 User #relation(fields: [player1Id], references: [id])
86 | player1Id String
|
want to keep track of all of the matches the user plays, each match has two players (Users)

Prisma - How to point two fields to same model?

I'm having trouble conceptualizing how to handle this issue. I've pored through the Prisma docs and other SO questions, but they all seem to be slightly different from this situation.
I have two models:
model User {
id Int #id #default(autoincrement())
firstName String? #map("first_name")
lastName String? #map("last_name")
email String #unique
password String
role UserRole #default(value: USER)
image String? #map("image")
createdAt DateTime #default(now()) #map("created_at")
updatedAt DateTime #updatedAt #map("updated_at")
friends Friend[]
##map("users")
}
model Friend {
id Int #id #default(autoincrement())
inviteSentOn DateTime #map("invite_sent_on") #db.Timestamptz(1)
inviteAcceptedOn DateTime #map("invite_accepted_on") #db.Timestamptz(1)
userId Int #map("user_id")
friendId Int #map("friend_id")
createdAt DateTime #default(now()) #map("created_at")
updatedAt DateTime #updatedAt #map("updated_at")
user User #relation(fields: [userId], references: [id])
// friend User? #relation(name: "FriendFriend", fields: [friendId], references: [id])
##map("friends")
}
I want to be able to set up the relationships on the Friend model to both point towards the User model, however I receive errors such as Error validating field 'friend' in model 'Friend': The relation field 'friend' on Model 'Friend' is missing an opposite relation field on the model 'User'.
I've tried adding the name property to the #relation field, but start receiving errors about ambiguous relations being detected.
How do I go about setting these relations up correctly?
You just need to provide name to disambiguate relation, like that:
model User {
id Int #id #default(autoincrement())
friend Friend?
friends Friend[] #relation(name: "friends")
}
model Friend {
id Int #id #default(autoincrement())
userId Int
friendId Int
user User #relation(fields: [userId], references: [id])
friend User #relation(fields: [friendId], references: [id], name: "friends")
}
And dont forget that both sides of relations need to have connections to the other.

How to get sql result with only rows that has a connected relations row

I am trying to query a database using the Prism Client and want to get back only the rows that has a foreign key in a joined table.
For example, get all users who have also created a post. I need a kind of "INNER JOIN".
I have tried something like:
return this.prisma.user.findMany({
where: {
Post: {
some: {
id: {
not: 0,
}
}
}
}
});
But the result is not the correct one.
I'm not sure how to use "none, some or every"
Suppose I have a schema like this:
model User {
id Int #default(autoincrement()) #id
name String
posts Post[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
model Post {
id Int #default(autoincrement()) #id
title String
user User? #relation(fields: [userId], references: [id])
userId Int?
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
I get the users without any posts via the following query:
const usersWithoutPosts = await prisma.user.findMany({
where: {
posts: {
none: {
id: undefined,
},
},
},
})
Could you try this way and check?