Relation two to many with Prisma - prisma

I'm trying to create a prisma schema with this kind of relation - I have two models: Player and Game. Every game is "played" by two players and I'm trying to connect them with something like this:
model Player {
id String #id #default(cuid())
name String
games Game[]
}
model Game {
id Int #id #default(autoincrement())
player_1 Player
player_2 Player
winnerId String
}
In this case I get an error which says Ambiguous relation detected. The fields player_1 and player_2 in model Game both refer to Player. Please provide different relation names for them by adding #relation(<name>).
And if I add relation with names which looks like this:
player_1 Player #relation(name: "GamePlayer1")
player_2 Player #relation(name: "GamePlayer2")
I get an error The relation field player_1/player_2 on Model Game is missing an opposite relation field on the model Player. I don't think that adding additional fields to Player model is necessary and also don't think that adding many to many relation which would look like this players: Player[] is smart.
What would be the right way to connect those two models based on my example?

You need to provide both player's id on Game and separate relation name on Player and Game. Here the right way to fix it:
model Player {
id String #id #default(cuid())
name String
games_player_1 Game[] #relation(name: "GamePlayer1")
games_player_2 Game[] #relation(name: "GamePlayer2")
}
model Game {
id Int #id #default(autoincrement())
player_1_id String
player_2_id String
player_1 Player #relation(name: "GamePlayer1", fields: [player_1_id], references: [id], onDelete: Cascade)
player_2 Player #relation(name: "GamePlayer2", fields: [player_2_id], references: [id], onDelete: Cascade)
winnerId String
}

Related

enum in prisma instead of table

I have two tables in my Prisma db. One is for admins and the other is for users, and since they differ a lot from each other I decided not to create an isAdmin field. They have both in common the establishment that is described as a table (one-to-many relation), but it has only one field (name). I'd like to know whether it is a good idea to create an Enum to represent this field. My only doubt is that, since the values of the enums can change (adding more fields dynamically), it is not as good as creating a table
model Admin {
id String #id #default(uuid())
pin Int
establishment Establishment #relation(fields: [establishmentId], references: [id])
establishmentId Int
}
model User {
id String #id #default(uuid())
name String
balance Float #default(0)
establishment Establishment #relation(fields: [establishmentId], references: [id])
establishmentId Int
}
model Establishment {
id Int #id #default(autoincrement())
name String
}
This is how I've imagined the new data source to be like
model Admin {
id String #id #default(uuid())
pin Int
establishment Establishment
}
model User {
id String #id #default(uuid())
name String
balance Float #default(0)
establishment Establishment
}
enum Establishment {
ESTABLISHMENT1
ESTABLISHMENT2
}
If you are sure that you won't need to store any more fields for Establishment then the enums approach is good. But in case in future you are envisioning that there could be other common fields, then you would need to duplicate them in Users and Admins Table and Enums approach won't be a fit.
Another approach could be to use the check constraint on database level to only allow two valid values i.e. ESTABLISHMENT1 and ESTABLISHMENT2, this way you won't even need to define enums.

Reuse same model for two fields in Prisma

My goal is for this:
I have a table of professions. A person can have two professions - a primary and secondary profession.
model Person {
id String #id #default(cuid())
PrimaryProfessionId String?
Secondary String?
PrimaryProfession Profession #relation(fields: [PrimaryProfessionId], references: [id])
SecondaryProfession Profession #relation(fields: [SecondaryProfessionId], references: [id], name: "secondaryProfession")
}
model Profession {
id String #id #default(cuid())
name String
Primary Person?
Secondary Person? #relation("secondaryProfession")
}
Trying to copy this: Prisma - How to point two fields to same model? but it doesnt work.
With current code I am getting error: Error parsing attribute "#relation": A one-to-one relation must use unique fields on the defining side.
What should I fix to make this work?

How can I filter by a value inside a pivot table (using Prisma)?

I'm building a bike rental app where users can reserve bikes for a certain number of days. Bikes and users have a many-to-many relationship, there's a bike_user pivot table that contains the information about reservation start and end dates. See the diagram:
My schema looks kinda like this:
model User {
id String #id #default(cuid())
username String #unique
email String #unique
rented_bikes BikeUser[]
}
model Bike {
id String #id #default(cuid())
model String
color String
rented_by_users BikeUser[]
}
model BikeUser {
user User #relation(fields: [userId], references: [id])
userId String
bike Bike #relation(fields: [bikeId], references: [id])
bikeId String
reservation_start_date DateTime
reservation_end_date String
##id([userId, bikeId])
}
My goal is to take a range of dates, and filter the bikes, showing only the ones that haven't been reserved between these two dates.
Can you please help me figure out how to do this?

What is the best way to model a one-to-many relationship that also has a "selected" object in Prisma?

In our app, a user can be a member of many organizations. While viewing the site, they are generally viewing it through one of those organizations. This is the selected organization.
Is the following model the best way to model that? Is there a way to model it so you don't have to have the selectedBy and selectedById on the Membership and just have the selectedMembershipId on the User with a foreign key to the Membership?
model User {
id Int #id #default(autoincrement())
memberships Membership[] #relation("Memberships")
selectedMembership Membership? #relation("Selection")
}
model Membership {
id Int #id #default(autoincrement())
user User #relation("Memberships", fields: [userId], references: [id])
userId Int
selectedBy User? #relation("Selection", fields: [selectedById], references: [id])
selectedById Int? #unique
organization Organization #relation(fields: [orgId], references: [id])
orgId Int
role MemberRole
##unique([userId, orgId])
}
It's not possible to do precisely what you're hoping to. The syntax for relations in prisma calls for having a relation field (To the best of my understanding, that's what you would prefer not to have in your schema).
Since it's a one-to-one relation, if you prefer, you could do it the other way around, and have a selectedMembershipId foreign key on the User side and only have the selectedBy relation field on the Membership side like this:
model User {
id Int #id #default(autoincrement())
memberships Membership[] #relation("Memberships")
selectedMembership Membership? #relation("Selection", fields: [selectedMembershipId], references: [id])
selectedMembershipId Int? #unique
}
model Membership {
id Int #id #default(autoincrement())
user User #relation("Memberships", fields: [userId], references: [id])
userId Int
selectedBy User? #relation("Selection")
...
}
However, this is really a matter of preference regarding which side to keep the foreign key. In my opinion, the way you're handling your schema is the most reasonable way to model the relationship in Prisma.

Can two fields reference the same field on another model

I have two models in my prisma schema for representing a sort of game schedule where 2 "players" can play against each other in a "matchup":
model Matchup {
id Int #id #default(autoincrement())
homePlayer Player #relation("Home Player", fields: [homePlayerId], references: [id])
homePlayerId Int
awayPlayer Player #relation("Away Player", fields: [awayPlayerId], references: [id])
awayPlayerId Int
}
model Player {
id Int #id #default(autoincrement())
homeMatchUps Matchup[] #relation("Home Player")
awayMatchUps Matchup[] #relation("Away Player")
}
I don't necessarily need to have the distinction of a "home" player and an "away" player however. I'd rather that the Player model have a single reference to any matchup they were associated with, as opposed to having to split it between two fields.
What would be the correct way to approach this?
It's not possible to have a single reference to Matchup from the Player side, you need to have two. So what you're asking for can't really be done.
The reason is, homePlayer and awayPlayer represent two separate one-to-many relations and you need to have a matching field in the many side (in this case Player) for every single one-to-many relation.