I'm starting Prisma for a project and I'm making the schema. I have a Customer table, and want to have a "referredBy" column, pointing to a customerId.
model Customer {
id Int #id #default(autoincrement())
uuid String #unique #default(uuid())
referralCode String?
referredBy Customer? #relation(fields: [referredById], references: [id])
referredById Int?
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
But it gives me an error.
Error validating field referreddBy in model Customer: The relation field referreddBy on Model Customer is missing an opposite relation field on the model Customer. Either run prisma format or add it manually.
It's not the first time I've encountered this. But usually it's for another table relation so I just add the opposite on the other table.
model Account {
id Int #id #default(autoincrement())
uuid String #unique #default(uuid())
**product Product #relation(fields: [productId], references: [id])**
customers Customer[]
}
I add
to the Product model:
Account Account[]
What kind of opposite relation field should I add?
Regards
Related
I have the following models in prisma schema:
model Order {
id String #id #default(auto()) #map("_id") #db.ObjectId
customer User #relation(fields: [customerId], references: [id])
customerId String #db.ObjectId
products Json
status String #default("pending")
paymentMethod String?
pixPayment Payment? #relation(name: "pixPayment", fields: [pixPaymentId], references: [id])
pixPaymentId String? #unique #db.ObjectId
creditCardPayment Payment? #relation(name: "creditCardPayment", fields: [creditCardPaymentId], references: [id])
creditCardPaymentId String? #unique #db.ObjectId
boletoPayment Payment? #relation(name: "boletoPayment", fields: [boletoPaymentId], references: [id])
boletoPaymentId String? #unique #db.ObjectId
total Float
createdAt DateTime #default(now())
##map("Orders")
}
model Payment {
id String #id #default(auto()) #map("_id") #db.ObjectId
paymentId Int
amount Float
paymentMethod String
customer User #relation(fields: [customerId], references: [id])
customerId String #db.ObjectId
payer Json?
installments Int #default(1)
status String #default("pending")
dateOfExpiration DateTime
dateApproved DateTime?
barcode String?
boletoUrl String?
pixQrCode String?
pixQrCodeBase64 String?
lastFourDigitsCard String?
cardHolder Json?
createdAt DateTime #default(now())
pixPaymentOrder Order? #relation("pixPayment")
creditCardPaymentOrder Order? #relation("creditCardPayment")
boletoPaymentOrder Order? #relation("boletoPayment")
##map("Payments")
}
I'm trying to create an Order document with the required fields (products, total, customerId), it works but only once, if I try to create another Order I get the error: "Unique constraint failed on the constraint: Orders_pixPaymentId_key". The pixPaymentId is an unique and optional field and in this case I'm not passing it.
Order create code:
const order = await prisma.order.create({
data: {
products,
total,
customerId: userId
},
select: {
id: true
}
});
I was expecting that would be possible to create multiple Orders documents without pixPaymentId as it is a OPTIONAL field, but I'm getting the Unique constraint error.
Prisma doesn't support unique and nullable feature yet.
For this case, we can only declare it as nullable and handle uniqueness manually. Same problem will occur when implementing unique and soft delete.
The reason why they don't support it because most database reject duplicate NULLs on unique constraint.
Follow this discussion: https://github.com/prisma/prisma/issues/3387
I'm using Prisma with an Express backend and React frontend. I was testing my delete request on Postman, and I keep getting this error:
"\nInvalid prisma.user.delete() invocation:\n\n\n An operation failed because it depends on one or more records that were required but not found. Record to delete does not exist."
I checked their docs, and unless I missed something—I can't really find much of an explanation. I'm also fairly new to relational databases, and this is the first time I've used Prisma.
My schema is incredibly long, so I'll post the relevant parts:
model User {
id String #id
email String #unique
firstName String
lastName String
approved Boolean #default(false)
usersDb Boolean #default(false)
volunteersDb Boolean #default(false)
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
avatarUrl String? #default("")
isActive Boolean #default(true)
lastLoggedIn DateTime #default(now())
role String #default("viewer")
volunteer Volunteer[]
}
model Volunteer {
id String #id #default(uuid())
userId String
dbUser User #relation(fields: [userId], references: [id])
My controller
const deleteUser = async (req, res) => {
const { id } = req.params;
await prisma.user.delete({
where: {
id,
},
});
Other than this, the table is behaving as expected and creating the relation to the Volunteer table. I feel like the error has something to do with that because I have another table without a relation, and the delete method works there.
Thanks in advance and happy to provide more info if necessary!
I figured this out and wanted to share. I was right, this had everything to do with the relation I'd created between the User and Volunteer table. When I tried to delete a record from the User table, I didn't tell Prisma what to do with the related records, so I got that error. I went back to my Volunteer model and made the relation fields optional, and the delete request worked. Here's the documentation on this, and here's my updated schema:
model User {
id String #id
email String #unique
firstName String
lastName String
approved Boolean #default(false)
usersDb Boolean #default(false)
volunteersDb Boolean #default(false)
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
avatarUrl String? #default("")
isActive Boolean #default(true)
lastLoggedIn DateTime #default(now())
role String #default("viewer")
volunteer Volunteer[]
}
model Volunteer {
id String #id #default(uuid())
userId String?
dbUser User? #relation(fields: [userId], references: [id])
I've just started learning nestjs and I'm using Prisma as my ORM, I've created two models (Employees, Clients), these models will contain foreign keys , the client will have the employee id and vice versa (a one-to-one relation), but as you will see in the models the employee will contain the whole Client "object", but what I want also is his client's id as an independent column :
this is the models:
model Employe {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updated DateTime #updatedAt
email String #unique
hash String
nom String
prenom String
// I want the client ID here too
client Client?
##map("employes")
}
model Client {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updated DateTime #updatedAt
email String #unique
hash String
nom String
prenom String
EmpId Int? #unique
emp Employe? #relation(fields: [EmpId], references: [id], onDelete: Cascade, onUpdate: Cascade)
##map("clients")
}
So is there any way ?
Framework: NestJS
ORM: Prisma
DB : Postgresql
Platform: Docker
In this link there is an example that can help you:
https://www.prisma.io/docs/guides/general-guides/database-workflows/foreign-keys/postgresql
I more or less understand what you mean. I don't understand why you don't set relation, but you can use this structure when creating a client or employe.
to create the employe
await prisma.employe.create({
data: {
email: 'blabla',
hash: 'balbla',
nom: 'blabla',
prenom: 'balbla',
clientId: 123,
include: {
client: {
...,
}
}
},
})
to create the client
await prisma.client.create({
data: {
email: 'blabla',
hash: 'balbla',
nom: 'blabla',
prenom: 'balbla',
employeId: 123,
include: {
employe: {
...,
}
}
},
})
The fields emp in the Client model and client in Employe model are relation fields so they won't exist in the database, they are just at the prisma level.
You only need to define the foreign key on one side of the relation - One to One relation Prisma reference
You could store clientId on the Employe model as well.
I am using prisma orm in nodejs and have the following schema (example)
model User
{
id Int #id #default(autoincrement())
answers Answer[]
}
model Product
{
id Int #id #default(autoincrement())
questions Question[]
}
model Question
{
id Int #id #default(autoincrement())
products Product[]
answers Answer[]
}
model Answer
{
id Int #id #default(autoincrement())
userId Int
user User #relation(fields: [userId], references: [id])
productId Int
product Product #relation(fields: [productId], references: [id])
questionId Int
question Question #relation(fields: [questionId], references: [id])
}
Is it possible to get a list of products with questions and with latest answer for each question?
The problem I have is, that nested includes don't respect grandparent id.
For example, in this code:
let products = await prisma.product.findMany({
include: {
questions: {
include: {
answers: true
}
}
}
})
returned answers for each question don't also belong to the product I want them to belong to.
What am I missing?
To the best of my knowledge, it's not possible to make the query you're looking for (A second layer of nested include that also respects the grandparent ID).
A possible workaround is to include the answers alongside the questions in the product query instead of nesting it inside questions. Then you can merge the questions and answers in the application layer (either in the backend or frontend, whichever is most appropriate).
The code would look something like this
let products = await prisma.product.findMany({
include: {
questions: true,
answers: true, // Assuming the relation field is called answers. You confirmed you accidentally forgot to mention the field in your schema.
},
});
// In Javascript/Typescript: For every product, iterate across every answer and add to the questions array.
This workaround should work reasonably well provided the number of products/answers isn't incredibly large.
I faced some problems when designing the schema.
case 1:
model User {
package: #relation(fields: [authorId], references: [id])
packageId: Int
}
model Package {
user User[]
}
one package can be subscribed by hundreds of users. So, I think this is the way to go. But, the problem is, when a package needs to be deleted, the user(admin) is also needed to be deleted. which we don't want
case 2:
model User {
package Package[]
}
model package {
author User? #relation(fields: [authorId], references: [id])
authorId Int?
}
by designing this way, when the package is deleted, the user is not deleted.
but I can't connect multiple users to a package.
I think you have to explicitly model the relationship from both sides to get a many-to-many relationship. After all users can subscribe to many packages and packages can have many users subscribed.
model User {
id Int #id #default(autoincrement())
packages Package[] #relation(references: [id])
}
model Package {
id Int #id #default(autoincrement())
user User[] #relation(references: [id])
}