One-to-One and One-to-Many Relationships in Prisma
00:00 So let's come down here. We'll make the user image first. So we'll say model, user image. And here, Copilot's going to fill this stuff in. Let's just check its work. That's an important part of AI-assisted programming. It is assisted. It is not the programmer yet. So here we have our ID.
00:17 It's going to be just like the other IDs that we've had so far, so that works fine. Our alt text is going to be optional, an optional string. Our content type, so this is like whether it's a PNG or a JPEG or WebP or whatever. So our content type there, that's important because when we serve it out
00:36 of the database on our image route, then we're going to need to know what content type to send back so that it displays properly. And then we have our blob. This is the bytes, the binary data that represents the image. And then our createdAt and updatedAt, that's pretty normal stuff.
00:55 And then we've got our user relationship here. And it's giving us a red underline because the user model doesn't encode anything about this relationship. So let's take a look at the relationship, make sure it's correct. The property we want to access the user on from the image is user, and that is part of the user model.
01:13 And then the relationship is established by our user ID, foreign key field. And we're referencing the ID field of the user model. And when the user is deleted, we want to cascade, and same with update. And then the user ID field needs to be unique. So this is the part that establishes that one-to-one relationship.
01:33 It says that a single user cannot have multiple images. If we try to create that, the database is going to say, uh-uh, you cannot have more than a single user with that. So we can get rid of all those instructions. And let's go up here.
01:50 And we'll say, when I want to access the image, I'm going to just say image. And that's going to be an optional user image. Here we go. Great, so let's do the note image version now. Model, note, image, and copilot, thank you. We've got our ID.
02:10 That looks great, our alt text. You know, there's a little bit of duplication here. I don't know. No, it's actually great. All of this is really good. It's not going to take up any more reasonable amount of data in the database. And it drastically simplifies our working with this stuff. I suppose the one drawback of this duplication
02:29 is if you decide, you know what, images, all of them should have alt text 100% of the time. We're going to make this a required field if we were going to do something like that. In that case, yeah, you would have to update that in two places. There's no way to represent this shared code in a Prisma schema, as far as I'm aware.
02:48 And yeah, so there's that. But you're grasping at straws there. Like, that's not a big deal in my mind at all. Great. And then we have our created at and updated at. And now our relationship with the note. So we want to access this on the note property. It is part of the note model.
03:07 And the relationship attribute says the field note ID, this is our foreign key, references the ID on the note, which is right here. And then when the note's deleted or updated, we cascade. So we'll apply that to these note images as well.
03:25 And then the note ID is the foreign key. It's a string. And then here, Copilot stuck in unique. And this is why you just don't accept everything that AI gives you. Because in our model that we've got right here, you can have more than one note image for a single note.
03:42 So we want to get rid of that. That is not a constraint that we want to apply. So let's go and update the note model so we can say what property those images should be on. So we'll say images. And that's going to be an array of note images.
03:58 And that establishes our relationship. So the second part of this is just to make sure that our model is correct is we need to update our database. So I'm going to copy that command here, npx prisma db push.
04:13 And so now if we restart Prisma Studio, then here we go. This is saying, hey, you're missing the note image. So let's show that one as well on both of these. So now we have an image field for both of these. And there's that one. Awesome.
04:33 So you can actually, if you would like, copy the Base64 that I gave you and stick that in here. So we're going to put that in our user image. So let's see. We're going to create a new record for the user image.
04:52 Add a record. The alt text, Cody profile. And the content type, image, JPEG. And then here's our blob. This actually includes the Base64 prefix, which we do not need to have.
05:10 So we'll stick that in there. And then our user will be Cody. And there's that. Save that change. And now our user has an image. So let's actually, if you don't want to do it that way or whatever, we're going to have a seed script that will
05:29 generate that image in there as well. So let's create that Prisma seed. So that's going to go in your Prisma directory under seed.ts. And I just gave you a bunch of code that you can copy and paste. We're going to just do that. And with that, we're creating a Prisma client.
05:48 We're finding the first note. So that should find this note right here. If that doesn't exist, we'll throw an error. We're going to improve this seed soon. Don't worry. And then we update the note where that we match that first note. And we're going to create some images. We're going to dive a little deeper into all the syntax here in a bit.
06:07 But if you take a look at our test fixtures, and then we've got Cody notes, we've got a bunch of images in here that you can use for your testing and stuff. So we're going to read that into a buffer,
06:22 and then that will get inserted as binary data in that blob. And so if we can run this following the command here, we use npxtsx prismaseed. Then that should create that image. If we go over to our note and refresh this and scroll over,
06:41 we've got two images right there. Ta-da. So we're in a good place with our schema. We can actually create images. And presumably, we'll be able to read them once we get to that point. So I hope you had an awesome time with that. Let's just quickly review the most important key learning outcomes of this as far as relationships are concerned.
07:01 So to establish this one-to-one relationship, we have the property on the user model to say, hey, I could potentially have a user image. And if I do, I want that to be on the image property. And then in our user image right here, we establish that relationship just
07:20 like the other relationships we had before. You don't always necessarily want onDelete or onUpdate to be Cascade, but most of the time in the things that I build, I typically will have those set to Cascade. And then you have your foreign key right here for the user ID.
07:39 And that's a string, and it is unique. That's what really makes the difference between a one-to-one relationship and a one-to-many relationship is that we're saying this field is unique. You cannot have more than one user image that points to this user ID.
07:57 And then we also made a note image that has lots of duplicate properties and establishes a one-to-many relationship with the note. And on the note, we said we can have many images. So there you go. That's your one-to-one and one-to-many relationship in Prisma.