Data modeling for Prisma - database

I have an application that needs to model some data, but I'm having trouble getting Prisma to recognize the appropriate relationships when building out the tables in my prisma.schema file.
I am trying to create a global list of "Interests", and I want users to be able to add to this list as well as choose interests from it. When users add items to "Interests", I want to tie the creation of that interest to the User (createdBy: userId), allow it to be selected by other users, and when selected by other users, tie their profile Id to a list of profile id's within that interest.
model Profile {
id Int #id #default(autoincrement())
bio String?
user User #relation(fields: [userId], references: [id])
userId Int #unique
interestList Interest[]
}
model User {
id Int #id #default(autoincrement())
email String #unique
name String?
posts Post[]
profile Profile?
interests Interest[]
}
model Interest {
id Int #id #default(autoincrement())
user User #relation(fields: [createdBy], references: [id]
//Don't understand what relational fields to add/modify to make this happen...
}

If I understand correctly, you want to create 1:n relation for createdBy (so 1 user can create n interests, but interest can be created only by 1 user) and than relation n:m for or profile that selected this interest?
so this can look like this way
model Profile {
id Int #id #default(autoincrement())
bio String?
user User #relation(fields: [userId], references: [id])
userId Int #unique
interests Interest[]
}
model User {
id Int #id #default(autoincrement())
email String #unique
name String?
profile Profile?
Interest Interest[]
}
model Interest {
id Int #id #default(autoincrement())
user User #relation(fields: [createdBy], references: [id])
createdBy Int
selectedBy Profile[]
}
If you want to connect selectBy to User not Profile check this documentation https://www.prisma.io/docs/concepts/components/prisma-schema/relations#disambiguating-relations

Related

Creating an associative table in Prisma Schema

I'm trying to model the following using Prisma for a personal project I'm working on.
The following schema for this I have put together is the following (I've removed some of the unnecessary session tables):
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id String #id #default(cuid())
name String?
email String? #unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
SpotList SpotList[]
}
// SpotSpot tables
model SpotList {
id Int #id #default(autoincrement())
userId String
name String?
description String?
public Boolean
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
User User #relation(fields: [userId], references: [id])
SpotListLocation SpotListLocation[]
}
model SpotListLocation {
list SpotList #relation(fields: [listId], references: [id])
listId Int
location SpotLocation #relation(fields: [locationId], references: [id])
locationId Int
##id([listId, locationId])
}
model SpotLocation {
id Int #id #default(autoincrement())
name String?
description String?
coords Unsupported("geometry(Point, 4326)")
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
SpotListLocation SpotListLocation[]
}
My question was basically two things:
Does my initial db design look sensible?
Is my schema a faithful representation of my design?
Bearing in mind, it's just a personal project for learning backend and DB mostly. I don't need it to be the most performant thing in the world. I just don't want it to be completely wrong :)

relating tables with the ORM prism

Using PostgreSQL, I want to make an application that manages Daily Habits. I'm trying to make a one-to-many relationship from the User tables to Habits and Habits to the other tables.
model User {
id String #id #default(uuid())
email String #unique
verify_email Boolean #default(false)
Habit Habit? #relation(fields: [habitId], references: [id])
habitId String[] #unique
##index([habitId])
##map("user")
}
model Habit {
id String #id #default(uuid())
title String
created_at DateTime
user User[]
dayHabits DayHabit[]
weekDays HabitWeekDays[]
##map("habits")
}
Creating habits, when there is more than one Habit, the new one overwrites the previous one.
rest of code
Creating one-to-many relations in Prisma is pretty straightforward as can be seen in the documentation
An example code of one-to-many relation between user and habit is
model User {
id String #id #default(uuid())
email String #unique
verify_email Boolean #default(false)
habit Habit[]
##index([id])
##map("user")
}
model Habit {
id String #id #default(uuid())
title String
created_at DateTime
user User #relation(fields: [userId], references: [id])
userId String
// dayHabits DayHabit[]
// weekDays HabitWeekDays[]
##map("habits")
}
Also, you didn't specify what you are trying to achieve with these fields dayHabits and weekDays.

Check if data record already exists (if no = create | if yes = do nothing)

i currently started with prisma.schema and mongodb
I have two collections with a field relations between Artwork and Like.
first is called "Artwork"
model Artwork {
id String #id #default(auto()) #map("_id") #db.ObjectId
name String?
mediaFile MediaFile[]
userId String? #db.ObjectId
user User? #relation(fields: [userId], references: [id])
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
like Like[]
}
second is called "Like"
model Like {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #db.ObjectId
user User? #relation(fields: [userId], references: [id])
artwork Artwork? #relation(fields: [artworkId], references: [id])
artworkId String? #db.ObjectId
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
If someone like a artwork i will create the following record in Like collection
{
userId: 'string',
artworkId: 'string',
}
Now i want to prevent, to create the exact same record in the collections table.
Is there a better way than to send a query beforehand if the dataset exists 1:1 like this?
You can create a combined unique index on userId and artworkId to only allow a single Like by a user or an artwork like this:
model Like {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #db.ObjectId
user User? #relation(fields: [userId], references: [id])
artwork Artwork? #relation(fields: [artworkId], references: [id])
artworkId String? #db.ObjectId
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
##unique([userId, artworkId])
}
Here's a reference for creating Compound Unique Index.

Prisma: What would be the best way to create relationships between 3 tables?

I have the following models.How can I create a relationship for these tables so that I can get the roles associated with group and group associated with roles.One group will have multiple roles.
Groups and Roles will be added separately though.Only after the Group is added can the roles be associated with them
model groups {
id Int #id #default(autoincrement())
group_name String? #unique
}
model roles {
id Int #id #default(autoincrement())
role_name String? #unique
}
model group_role_association {
id Int #id #default(autoincrement())
group_id Int
role_id Int
}
This seems like a use case for an implicit relation. This is a feature of Prisma that allows you to model a m-n relatinshiop between to tables without managing a relation table (in your example, I read group_role_association to be a relation table rather than an actual "model")?
model groups {
id Int #id #default(autoincrement())
groups_name String
roles roles[]
}
model roles {
id Int #id #default(autoincrement())
role_name String
groups groups[]
}
Also, I'd actually recommend you to use Prisma's naming conventions (i.e. spell model names in singular form and PascalCase notation):
model Group {
id Int #id #default(autoincrement())
name String
roles Role[]
}
model Role {
id Int #id #default(autoincrement())
name String
groups Group[]
}

The best way to have many types of user in the same database

I building an app with 5 different users, and each user have different fields. What is the best way to model the database? im creating one table for each user, is the best way or exist another different way like put all in one table? Im not talking about performance, just the best way to organize.
Look what i have:
model CoordinatorProfile {
id String #id #default(uuid())
name String #db.VarChar(255)
image Image? #relation(fields: [imageId], references: [id])
imageId String? #unique
school School?
user User?
createdAt DateTime #default(now()) #db.Timestamp
updatedAt DateTime #updatedAt #db.Timestamp
deleted Boolean #default(false) #db.Boolean
}
model TeacherProfile {
id String #id #default(uuid())
name String #db.VarChar(255)
image Image? #relation(fields: [imageId], references: [id])
imageId String? #unique
school School #relation(fields: [schoolId], references: [id])
schoolId String #unique
team Team[]
user User?
createdAt DateTime #default(now()) #db.Timestamp
updatedAt DateTime #updatedAt #db.Timestamp
deleted Boolean #default(false) #db.Boolean
}
model StudentProfile {
id String #id #default(uuid())
name String #db.VarChar(255)
image Image? #relation(fields: [imageId], references: [id])
imageId String? #unique
school School #relation(fields: [schoolId], references: [id])
schoolId String #unique
team Team? #relation(fields: [teamId], references: [id])
teamId String?
user User?
text Text[]
createdAt DateTime #default(now()) #db.Timestamp
updatedAt DateTime #updatedAt #db.Timestamp
deleted Boolean #default(false) #db.Boolean
}
model User {
id String #id #default(uuid())
email String #unique #db.VarChar(255)
password String #db.VarChar(255)
access_until DateTime #db.Timestamp
student_profile StudentProfile? #relation(fields: [studentProfileId], references: [id])
studentProfileId String? #unique
corrector_profile CorrectorProfile? #relation(fields: [correctorProfileId], references: [id])
correctorProfileId String? #unique
coordinator_profile CoordinatorProfile? #relation(fields: [coordinatorProfileId], references: [id])
coordinatorProfileId String? #unique
teacher_profile TeacherProfile? #relation(fields: [teacherProfileId], references: [id])
teacherProfileId String? #unique
roles Role[]
createdAt DateTime #default(now()) #db.Timestamp
updatedAt DateTime #updatedAt #db.Timestamp
deleted Boolean #default(false) #db.Boolean
}
enum Role {
Estudante
Administrador
Professor
Corrector
Coordenador
}
You can extract profile data which is common between user types in a separate table for instance profiles, and create separate tables for each user type, teachers, administrators ...
For extracting to work you need to:
don't reference sub types in root, reference root type in sub types instead
separate concerns, so users table is just for access management purposes and profiles table is just for data storage and retrieval
model Profile {
id String #id #default(uuid())
name String #db.VarChar(255)
image Image? #relation(fields: [imageId], references: [id])
imageId String? #unique
school School?
user User?
createdAt DateTime #default(now()) #db.Timestamp
updatedAt DateTime #updatedAt #db.Timestamp
deleted Boolean #default(false) #db.Boolean
}
model Coordinator {
id String #id #default(uuid())
profile Profile
}
model Teacher {
id String #id #default(uuid())
team Team[]
profile Profile
}
model Student {
id String #id #default(uuid())
schoolId String #unique
team Team? #relation(fields: [teamId], references: [id])
teamId String?
text Text[]
profile Profile
}
model User {
id String #id #default(uuid())
email String #unique #db.VarChar(255)
password String #db.VarChar(255)
access_until DateTime #db.Timestamp
createdAt DateTime #default(now()) #db.Timestamp
updatedAt DateTime #updatedAt #db.Timestamp
deleted Boolean #default(false) #db.Boolean
}
But...
In the end it would not help if you don't consider what behaviors are needed in the software you're gonna build to use it, and what kind of queries you will need.
for example if you want to be able to query all user types in a single query, that might be a sign that you want to also manipulate those data, which is very hard to do in the design specified above.

Resources