Both two Prisma schema have foreign key of each other's ID - prisma

model Users {
id Int #id #default(autoincrement())
business_id Int? #db.Int
Businesses Businesses? #relation(fields: [business_id], references: [id], onUpdate: Cascade, onDelete: Cascade)
name String #db.VarChar(255)
surname String #db.VarChar(255)
email String #unique(map: "email") #db.VarChar(255)
password String #db.VarChar(255)
}
model Businesses {
id Int #id #default(autoincrement())
name String #db.VarChar(255)
owner_id Int #db.Int
Users Users #relation(fields: [owner_id], references: [id], onUpdate: Cascade, onDelete: Cascade)
phone String #db.VarChar(255)
}
So the logic is like this that in the Model User the value of business id is opsional and in the Business's model the owner_id the ID is mandatory.
In the User's table I am getting this error:
Error parsing attribute "#relation": The relation fields `Users` on Model `Businesses` and `Businesses` on Model `Users` both provide the `fields` argument in the #relation attribute. You have to provide it only on one of the two fields.
And in the Business's model this error:
Error parsing attribute "#relation": The relation fields `Users` on Model `Businesses` and `Businesses` on Model `Users` both provide the `references` argument in the #relation attribute. You have to provide it only on one of the two fields.
Relationship Between User -> Business: many to one ( many users can be part of one business)
Relationship Between Business -> User : one to one (only one user can be the owner of one business)

Given the assumptions/relationships in your question
One business can have many users, each user can belong to only one business (one to many relationship, called "business2user" in the schema below)
One user can own one business, a business is owned by one user. (one to one relationship, called "business2owner" in the schema below)
a prisma.schema could look like this:
model User {
id Int #id #default(autoincrement())
business_id Int? #db.Int
business Business? #relation(fields: [business_id], references: [id], name: "business2user", onUpdate: Cascade, onDelete: Cascade)
name String #db.VarChar(255)
surname String #db.VarChar(255)
email String #unique(map: "email") #db.VarChar(255)
password String #db.VarChar(255)
ownedBusiness Business? #relation(name: "business2owner")
}
model Business {
id Int #id #default(autoincrement())
name String #db.VarChar(255)
owner_id Int #unique #db.Int
owner User #relation(fields: [owner_id], references: [id], name: "business2owner", onUpdate: Cascade, onDelete: Cascade)
users User[] #relation(name: "business2user")
phone String #db.VarChar(255)
}
I took the liberty to rename Users to User and Businesses to Business to improve interpretability.

Related

Prisma: How would I link multiple columns to the same data type

New to relational databases, and am using Prisma with Postgres, and Nextjs for a project. I am sending out emails to customers, and want to store these emails, but don't fully understand how the relationships work, to get it fully working.
I have email recipients that relate to a customer. Here there is a name and email address.
model email_recipient {
id String #id(map: "pk_email_recipient") #db.Uuid
name String #db.VarChar(255)
email_address String #db.VarChar(255)
customer_id String #unique #db.Uuid
customer customer #relation(fields: [customer_id], references: [id])
}
And I have an email model, that has to, cc, and bcc columns, that could be multiple email recipients. The recipient could technically exist in all three.
model email {
id String #id(map: "pk_email") #db.Uuid
body String? #db.Text
created_date DateTime? #db.Timestamp(6)
last_modified_date DateTime? #db.Timestamp(6)
to email_recipient[]
cc email_recipient[]
bcc email_recipient[]
}
Prisma attempts to generate relationships for me, but I doesn't fully work as it adds the same named field 3 times, like so.
model email_recipient {
id String #id(map: "pk_email_recipient") #db.Uuid
name String #db.VarChar(255)
email_address String #db.VarChar(255)
customer_id String #unique #db.Uuid
customer customer #relation(fields: [customer_id], references: [id])
user user[]
email email? #relation(fields: [emailId], references: [id])
emailId String? #db.Uuid
email email? #relation(fields: [emailId], references: [id])
emailId String? #db.Uuid
email email? #relation(fields: [emailId], references: [id])
emailId String? #db.Uuid
// Clearly an issue here, but not prismas fault, its just trying its best.
}
I have attempted to add an intermediary table in between with a recipient type enum, but could not get that to work. I think it is the right solution, but this is where my understanding of relationships break down.

Does Prisma create a new relationship collection when using MongoDB?

Looking at the Prisma docs and they show the example below. In this instance, if I'm using MongoDB and define my schema as per below, does Prisma create a collection for me called _CategoryToPost on my behalf to record the many to many relationships?
Or do I have to create my own collection to document this relationship?
model User {
id Int #id #default(autoincrement())
email String #unique
name String?
role Role #default(USER)
posts Post[]
profile Profile?
}
model Profile {
id Int #id #default(autoincrement())
bio String
user User #relation(fields: [userId], references: [id])
userId Int #unique
}
model Post {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
title String
published Boolean #default(false)
author User #relation(fields: [authorId], references: [id])
authorId Int
categories Category[] #relation(references: [id])
}
model Category {
id Int #id #default(autoincrement())
name String
posts Post[] #relation(references: [id])
}
enum Role {
USER
ADMIN
}
Link to docs
Prisma will create the necessary collections when you run the npx prisma db push command. You should not need to worry about the underlying structure beyond that.

Prisma One-to-one relation issue

I have just recently started using prisma and I ran into an issue with relations. I have a user model and an address model.
model User {
id Int #id #unique #default(autoincrement())
username String
}
model Address {
id Int #id #unique #default(autoincrement())
street String
}
I need to add 2 addresses to the user: invoicing address and delivery address. In the address I don't need a user reference.
I thought this would work without issues by adding this to the user model:
invoiceAddress Address? #relation(name: "iAddress", fields: [iAddressId], references: [id])
deliveryAddress Address? #relation(name: "dAddress", fields: [dAddressId], references: [id])
iAddressId Int?
dAddressId Int?
But when saving the schema two user fields are added to the address model... which I don't need and now I have issues because they reference the same user model so I have to also name them and add scalar field...
Am I missing something??? This should be a basic use case imo.
This is a requirement from Prisma's end that relation fields should exist on both sides of the model, you cannot define relation field on only one model.
The following schema model should solve the issue for you:
model User {
id Int #id #unique #default(autoincrement())
username String
invoiceAddress Address? #relation(name: "iAddress", fields: [iAddressId], references: [id])
deliveryAddress Address? #relation(name: "dAddress", fields: [dAddressId], references: [id])
iAddressId Int?
dAddressId Int?
}
model Address {
id Int #id #unique #default(autoincrement())
street String
UserInvoice User[] #relation(name: "iAddress")
UserDelivery User[] #relation(name: "dAddress")
}
Please note that relation fields do not exist on database so UserInvoice and UserDelivery columns would not exist on Address table. Similarly invoiceAddress and deliveryAddress columns would not exist on User table.

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.

Prisma schema one-to-many relations from multiple tables to one

I want to acomplish such schema, where user could have some images and recipes could have some images.
I came up with solution, but it throws this error for author and recipe rows in image model. My solution is to use type column as diferentiator between Recipe and User types.
Error parsing attribute "#relation": The given constraint name images_parentId_fkey has to be unique in the following namespace: on model Image for primary key, indexes, unique constraints and foreign keys. Please provide a different name using the map argument.
My solution:
model User {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
images Image[] #relation("UserImages")
Recipe Recipe[] #relation("RecipeAuthor")
##map("users")
}
model Recipe {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
authorId String #db.Uuid
author User #relation("RecipeAuthor", fields: [authorId], references: [id])
images Image[] #relation("RecipeImages")
##map("recipes")
}
model Image {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
type String
parentId String #db.Uuid
author User #relation("UserImages", fields: [parentId], references: [id])
recipe Recipe #relation("RecipeImages", fields: [parentId], references: [id])
##map("images")
}
Only other solution I came up with is to create multiple tables for images, something like user_images and recipe_images, but i dont really like that and I might need even more tables like this in future, so I would rather find better way. Thanks in advance for any help :)
Instead of using parentId for both in UserImages and ReceipeImages relation. You can separate them out and have something like parentUserId and parentReceipeId.
The following solution could potentially work:
model User {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
images Image[] #relation("UserImages")
Recipe Recipe[] #relation("RecipeAuthor")
##map("users")
}
model Recipe {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
authorId String #db.Uuid
author User #relation("RecipeAuthor", fields: [authorId], references: [id])
images Image[] #relation("RecipeImages")
##map("recipes")
}
model Image {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
type String
parentUserId String? #db.Uuid
parentReceipeId String? #db.Uuid
author User? #relation("UserImages", fields: [parentUserId], references: [id])
recipe Recipe? #relation("RecipeImages", fields: [parentReceipeId], references: [id])
##map("images")
}