NestJS & Prisma Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video I'm going to teach you how to use Prisma in your nest application Prisma is an object relational mapper for SQL and nosql databases such as MySQL and mongod DB with Prisma you use a schema based approach to Define your models and those models map to a database table for relational databases or a document for no SQL databases it's very popular and easy to use so let's go ahead and get started with setting up Prisma I went ahead and created a very simple project for us it has two modules and it has a controller and a service already set up though we still need to implement methods and implement the logic for those methods we'll focus on the users module first and then later on we will work on the posts module so the first thing that we're going to do is set up Prisma so to get started we need to go ahead and install Prisma for our project so in your terminal type npm I hyphen D Prisma so we'll save Prisma as a developer dependency and this will install the Prisma CLI for us and if you look at your node modules folder you should see that there is this Prisma binary right over here inside the bin folder so we can use the Prisma CLI by typing npx Prisma and this will allow us to use the Prisma CLI so what we want to do is initialize Prisma so we're just going to type npx Prisma in it just like this and what this will do is create a folder called Prisma as you can see on the left hand side and it will also create a EnV file so this Prisma folder will contain everything related with your Prisma schemas when we get into database migrations they will also be inside this Prisma folder ER as well so the first thing that you'll see here is this generator client you don't have to worry so much about this all you need to know is that this takes care of actually generating the assets based on your Prisma model so the way that it works is when we Define a Prisma model that Prisma model is going to map to a database table for our SQL database and then what we're going to need to do is generate these assets based off of our Prisma model and those assets are pretty much just typescript types or interfaces classes things like that but mostly they're actually just types and interfaces that Prisma will generate for you and this is what is going to allow you to interact with your database using the Prisma client while also having type safety when you reference your models such as a user or a post you'll see later on when we reference the Prisma client on what I'm talking about right over here we have our data source and we have a provider so by default it configures it to use postgres we're just going to set it to my SQL but again if you're using postgres you can leave it alone as postgres and then we have the URL set right over here and it uses EnV to point to this database URL which is inside the EnV file which was created for us when we ran npx Prisma inits so it just has this database URL I'm going to go ahead very quickly configure it so since I'm using my SQL I'm going to change postest to my SQL and then over here here we want to configure our username and password so right where it says John do that's the username so you're going to type your username so I'll put mine test user and then where it says random password this is where you're going to put your password for your database user account so mine is test user 123 so test user colon and then test user 23 and then at so this over here Local Host my database is running locally so I'm going to leave it as Local Host but if you're using a remote database then you would make sure you provide the remote server host name so I'm going to leave it as Local Host and then the port is going to be 3306 and then for the database itself I'm going to go ahead and call it nestjs Prisma DB so let's go ahead and go back to our schema. Prisma file now one thing that I do want to mention very quickly is you want to make sure you also install the Prisma extension inv vs code so you want to go over to extensions and you want to search for Prisma and then you want to install this one right over here here so this will make sure that you have syntax highlighting formatting autoc completion all those kind of things so that's the reason why you can see that some of these keywords are highlighted and there's color highlighting over here so just wanted to mention that very quickly so what we want to do now is we want to go inside our schema. Prisma file and we want to create our first model so I'll create a few so let's start off with a simple user model so we're going to use the model keyword and we're going to give our model a name so I'll call it user and then provide a pair of curly braces so inside my model I want to go ahead and Define fields for this model which will then get mapped into a column in our user table in the database I'm going to start off with a simple ID and the data type Prisma also has their own data types as well so I'm going to set it as int just like this there's also big in if you need big in but I'll leave it as int for now and I want to make sure that this user ID field is a primary key and that also Auto increments every single time we create a new user so to do that I'm going to need to use what is called an annotation as well as an annotation function so there is this annotation called default and then inside default we can provide a default value so I can provide 1 2 3 or I can provide a string if this ID was in fact a string but in this case I want the default value to be an autoincrement value so we're going to use The autoincrement annotation function and that is passed in as an argument to default just like this now since this ID is going to be an actual primary key we also want to make sure that we use the ID annotation right over here so that way we let presma know that this is actually going to be a primary key so let's go ahead and Define a few more Fields we'll do one for username so this is going to be a string and I want to make sure that my my username for this user model is going to be unique because we don't want multiple records in our database having the same exact username that wouldn't make any sense in in a realistic application so we can use the at unique annotation just like this and this will Mark username as a unique value and let's go ahead and do one for display name so display name I want this to be a string but I also want to mark it as optional so what I can do is I can use the question mark operator Ator at the end of the data type so this marks display name as optional or nullable if you wanted to add a default value for display name you could also just do at default and pass in an empty string like this okay let's create a few more models so for now we will only use the user model but later on in the video when we get to one to one and one to many and many to one relationships I'll show you how we can connect the user model with our other models that we're going to create so I'll create a model called user setting and this will just relate to settings for the user so let's say for example we want them to have a setting to indicate that they have notifications enabled so we'll do notifications on and this will be Boolean just like that and we also want to make sure that this user setting model also has a unique ID so that could be very similar to what we have for our user model so for user setting I'm going to go ahead and just copy and paste the same exact thing right over here okay but this ID is for the user setting model so so let's go ahead and do one do another field we'll call this SMS enabled and we'll set this to be a bing we'll keep it very simple for now and I'll go ahead and Define one more model I'll call it posts or post and we need the same thing we need an ID a primary key so we're going to do the same thing right over here and then I'll have a title for the Post which is going to be a string and then I want a description as well and then we'll leave the other stuff for later on in this video because we of course for this post we want to relate the user with the post and we also want to relate the user with a user setting but we'll save that for later on in the video when we get to relations so now what we need to do is we need to run a database migration or a SQL migration in this case so every single time you perform some kind of update with your model in Prisma you need to make sure you run a migration what that does is it will take the changes that you made to your model and actually apply them to the actual database itself so we need to First go into our terminal so let's go here and then what I'm going to do is type npx Prisma migrate Dev and then we want to give this migration a name so I'll go ahead and do hyphen hyphen name and I'll just call this init DB just like that and I'm going to go ahead and hit enter and what's going to happen is you're going to see that a bunch of stuff happen so first it was able to successfully connect to the database so that's good so it was able to create the database as you can see right over here because the database did not exist and then it creates this migration this migration. SQL file right over here and all this literally is is just a bunch of SQL queries so you can see that we are creating a table called user creating the user setting and the post so once this migration. SQL file is created it's going to go ahead and execute that file to create the actual tables in this case so once that is done there's a command called Prisma generate which is automatically invoked whenever we run Prisma migrate and this is where it will actually take the updates of your model so if there are any updates it'll go ahead and generate assets for you and you can actually take a look at it inside the node modules folder if you actually go inside Prisma you can actually go inside the index.js file and you can search for it it's somewhere over here so you can see over here we have one for user scaler field enum and then we have the ID username display name and then this is the user settings scaler field enum and this is post right over here so they are creating these types for us and there's a bunch of more types that are generated for us whenever we run Prisma generate so we'll explore them later on but I just want to show you very quickly where you can find that inside this Prisma folder so now what we can actually do is we can actually go into our code and reference the Prisma client using the Prisma client we can actually interact with our database and create records for a user user setting a post we can go ahead and query the database to retrieve the records we can update the records whatever it is that we want we can now do that with the Prisma client now one thing that I will also mention is that when you run Prisma migrate for the first time it will also install the Prisma client for you so you can see that in my package.json file I have Prisma client as a dependency which I did not install myself so I just wanted to mention that but if for for some reason you don't have Prisma client just make sure you install it by typing NP PMI at Prisma client just like that so let's go ahead and run our code let's start up our server let's type npm Run start colon Dev let's make sure everything is working fine so you can see that our entire code is working there are no errors and if you want to what you can do is you can actually log into your own database so I'll do that very quickly so use nestjs Prisma DB and I'm going to type show tables and you can see that I have all of my tables created right over here and I can describe each table you can see that this is the schema definition for my user table and you'll see how they are properly mapped to an actual database table from those Prisma models so just wanted to show you that very quickly so let me move this to the other screen so now we want to actually use the Prisma client in our nestjs project so what we can do is first let's create a new module so I'm going to create a new folder I'm I'm going to call it Prisma and I'm going to create a new file and I'll call it Prisma module. TS so the reason why I'm doing this is because I want to be able to create this Prisma module and then I want to be able to import it anywhere in my application that I that I need it so we're going to use the module decorator and we'll use that to annotate this Prisma module class that I'm creating and inside the module decorated we want to pass an object and we want to set we don't really have any Imports we really only are going to need providers and exports so let's go ahead and create another file and I'll call it Prisma do service.ts and I'm going to create a class and I'll call this Prisma service and this Prisma service is going to be a provider so let's mark it with the injectable decorator like that and I want to extend the Prisma client class okay just like this so we're going to import Prisma client from the at Prisma client package just like this and then what we want to do is we want to implement this on module in its interface which comes from the core nestjs Library okay nestjs common so what I want to do is I want to implement this on module init method just like that and essentially what I want to do is whenever this Prisma service class is initialized I want to go ahead and connect to the database if you don't do this which you don't have to what happens is whenever you try to query the database it's going to lazily connect to database okay Prisma will lazily connect to database so we can go ahead and reference this Dot and since we extended the Prisma client class we inherit all of these methods that come from Prisma client so we want to go ahead and call this do connect this dollar sign connect method me like that and this returns a promise so I can go ahead and actually just do I can handle the Promise by calling. then we don't really need to do anything else I'm just going to go ahead and just write a console log and say connected to DB and then if there are any errors we'll catch we'll handle it by catching it and I'll just go ahead and do console log error connecting to DB or actually you know I'll just log the error just like that now what we want to do is add our Prisma Service as a provider in our Prisma module so let's do that Prisma service add that to the providers array now since we're going to be importing the Prisma module to our users module right over here and our post module later on we want to make sure that we add the Prisma Service as an export because we are going to need to inject the Prisma service into our users service class so I'm going to go ahead and copy this and just add that over there and just close out of the prismo module file so now if I go into my users. service.ts file I can go ahead and first set up a Constructor and before we inject the Prisma service we want to go ahead into users. module. TS and we want to go ahead and import Prisma module just like that let's make sure that our dependencies are successfully initialized and you can see right over here in the console you can see that Prisma module dependencies initialized and you can also see that it was able to successfully connect to the database so that's good okay and if I remove that and save it's going to go ahead and and not do anything at all so this verifies that the Prisma module is in fact being successfully initialized so that's good so now we can go back to the users service class and I'm going to go ahead and inject the Prisma client or the Prisma service so private Prisma and then Prisma service just like this if I look at the logs you can see that everything is good okay there are no issues with injecting the Prisma service into our users service class because we have Prisma module set up over here if I were to remove that import remove that from the Imports array you can see now it is complaining okay so hopefully this makes sense so let's go ahead and continue so now inside our user service we're going to define a few methods so let's do one for creating a user and then we'll do one for getting a user or get users and then we'll do one for get user by ID just like this okay we'll start off with these three for now we'll Implement uh these as we go along so we'll start off with create user first okay so create user is going to need an object that is going to have all the fields that we're going to use to create the user itself we'll worry about that in just a little bit but what I can do here is I can reference this. Prisma and you see how right over here I have this user property as well as post and user setting so this allows you to reference the actual Prisma model itself and you can actually perform operations on these database models so by referencing this. Prisma do user I can actually reference a bunch of these methods as you can see right over here so for example if I wanted to create a user I would call do create just like this and then I would pass in the appropriate argument ments to actually create the user itself if I wanted to get a user then I would use something like find first or find unique there are a bunch of different methods that you can use so we'll explore them as we progress so now here's the thing though with our user service and let me just kind of like close the terminal so I can zoom in a little bit more so with our create user method inside our user service class we need arguments right we need an argument that represents the object that is going to contain the actual fields that the user is going to require in order to be created in the database so Prisma actually has these autogenerated types that you can use so you don't have to create them yourself so what I mean by that is let's say for example I'll call this argument create user data and then I can type annotate it with this Prisma so let me import Prisma from at Prisma client and then if I reference Prisma right over here you can see that there are a bunch of different types that we can reference right over here so if I wanted to have one for user let's see there's one right over here post create or not not post create it's user create input just like that okay so you can actually use these autogenerated uh inputs that were done by Prisma to represent your data that you want to actually create okay so if you actually go to the definition you can see that it's just a regular type username and then display name just like that so now while you should use these autogenerated types we also want to make sure that we are validating our data as well so we will also still need a dto for the control Lo and I'll and I'll explain a little bit about that in just a little bit but you can see that I am type annotating create user data just like this so it's good to use this so that way we are consistent with what we are passing into our method calls when we interact with the Prisma client okay so for example we know that the only fields that we need are username and display name there's not going to be a need for the ID field because that is autogenerated so what I can do here is I can return this. Prisma and then reference user and call create and then we want to pass in this data property which is going to map to our create user data object just like that okay and I'm just going to rename this to data so I can just remove this right hand side all right so now all we need to do is just go into our users controller and we want to inject our user service so let's do that private user service and type annotate with users service class and then we'll go ahead and set up a post request so I'm going to use the post decorator and I'll call this method create user and we're going to want to call this. user service. create user and then we need to pass in data so we need to first get the request body so we can do that by using the at body decorator just like this but we need a dto okay so here's the thing though some people might wonder well couldn't I just use the same Prisma type right over here user create input well you shouldn't because there's there's a few reasons why first of all you wouldn't actually be able to use something like class validator and the class validators decorators to properly validate each field and this itself is a type and typically for dto you want to actually use a class so it's good practice to actually use a dto alongside with the autogenerated Prisma inputs so what we'll do is we'll create a user dto so let me just call this create user dto and inside the users folder I'll create a new folder called dto I'll create a new file called create user dto or create user. D.S so I'll create a class called create user dto and this is going to represent our request body so remember we have a username of type string and display name which is a string and it is also nullable it's optional okay so I want to use class validator to properly validate all of these fields in the request body layer so I'm going to go ahead and install a package called class validator so npmi class hyen validator just like this and let's just run our server again okay wonderful so now I'm going to go ahead and for my username field I'm going to first make sure that this username field is in fact a string so I'm going to use the is string decorator and that comes from class validator and then I'm also going to make sure that it is not empty so I'm going to use is not empty just like that for display name we also want to make sure that this is a string if they do provide it but we also want to mark it as optional so we'll use the is optional decorator so that way it won't complain about us not providing the display name so let's go back to our controller and we want to use this use pipes decorator for the create user method and I'm just going to pass in this validation pipe just like this this validation pipe class and so this will enable validation for our request body for this endpoint okay so let me just go ahead and continue type annotating the create user dto with the create user dto class that I just created and now we have proper validation for the request body so that's good so we can go ahead and just pass in create user dto to create user just like this okay and there shouldn't be any issues with that all right so let's go ahead and test out our endpoint let's just first make sure that there are no errors in the console let's see and it's also saying that the class Transformer package is missing uh oh yeah let's also install that as well so npmi CL class Transformer yeah these two packages go well in hand class Transformer with class validator it's complaining about this because we installed class validator without class Transformer so make sure you do install that okay so let's run our server again make sure there are no issues okay wonderful there are no issues whatsoever so now I can go in to my thunder client you can use whatever HTTP client you want you can use Postman whatever it is you want I'm going to use Thunder client I'm going to create a new request it's going to be a post request and the URL is going to be Local Host at Port 3000 SL users okay so we're going to make a post request if I send an empty request body it's going to complain about the username so we need to make sure we provide the username so let's do Anson display name is optional so if I click Send this should work and now you can see that there are no errors it successfully created our user so what happened was we validated the request body and then we called this. user service. create user okay and then inside over here create user we called this. Prisma do user. create we passed in the data and then we we just returned whatever it was that is returned okay we don't have to do additional things such as manually saving to the database like you have to do it in type RM Prisma just does all of this for you in one single line so you don't have to worry about it so the user that was created was returned as a response which you can see right over here now if I try to create another user with the same username it's going to error out because remember we have that unique constraint on the user itself or on the username if I show you the logs right over here you can see it says unique constraint failed on the constraint user username key that constraint is in fact working properly let's go ahead and create another user let's do display name this time andon to Dev there we go it created one just for us okay so now we know how to create users so that's good let's go ahead and actually query our database to retrieve a list of users so going back to our users. service.ts file what I can do is inside get users I can return this. Prisma do user and I can call this find many method so what this will do is this will get you all the users based on some filter some criteria in our case we don't really need one right now but this is very helpful if you want to filter users based on their username based on their display name so for now we'll just get back all the users so we want to go ahead and call this get users method in the users control so let's set up a get request so we're going to use the get decorator and we'll go ahead and call this method get users and we'll just return this do user service. getet users just like that and this will return an array of users so if I go into Thunder client if I make a get request to the users endpoint it's going to give me back two users that I created okay the array of users just like that okay so hopefully that makes sense now let's say if I want to get a user by its ID that isn't so difficult so the first thing that we need is the ID of the user so inside the user service for get user by ID I'm going to expect one argument the ID which is going to be a numeric value okay because remember our ID for the user is a number so what we're going to do is on the user reference for on the Prisma client itself we're going to call find unique okay so since we know that these IDs are going to be unique there's not going to be two users with the same ID we can use find unique in this case okay so in find unique we want to pass in an object and this object is going to have this wear property that we need to set which is going to be an object and this is where you're going to set the actual condition based on the user that you want to find so in this we want to search by the ID so we want to set the ID property just like this so ID maps to ID just like that but we can do it Shand because the field name is the same name as the argument over here so this will search for the user by its ID now if you need to search for the user by the username because we know the username field is unique then you would just replace ID with username like this and then you would pass in the username value okay so hopefully that makes sense let's go ahead and go into our users's controller and let's set up an endpoint to get the user by the ID so we're going to use a get request this time we're going to specify a route parameter so it's going to look like colon ID just like this and then we're going to call the method get user by ID and we're just going to Simply grab the route parameter From the Path and we can do that by using the app params or app pram decorator and then I can just specify the route parameter that I want to get so ID now keep in mind that this parses the route parameter as a string we want to make sure that it is a number so you want to go ahead and as a second argument to the pram decorator we want to pass in this parse int pipe just like this so this will take care of not only validating the route parameter for us but also transforming it from a numeric string into an actual numeric value so then I'll type annotate ID into number just like that and remember parse in pipe is imported from nestjs common okay so now what I'll do is I'll just return this. users service. get user by ID we we'll just return that method call and now watch this if I go ahead and try to pass in an ID for the user that that I know does not exist to 100 so it's it's still going to return a status of 200 we'll fix that in just a little bit but notice how if I pass in a string like this ABC it's going to give me a 400 status code it's going to say validation failed numeric string is expected okay so that's good but if I pass in let's say ID of one it's going to give me back this user right over here okay let's go ahead and adjust our logic so what we'll do is this so This find unique actually returns a falsy value if the user was not found okay so for example if I do const user equals await this. user service. get user by ID let's make sure we add a sync in front of get user by ID in our controller method I'll console log the user just to show you what happens if the user itself is not found oops okay so if I do let's do 10 you're going to see it says null so what we can do is let's say if the user is not found then I can go ahead and do this if user is not found throw a new HTTP exception and that's also imported from NJ com in the HTTP exception class and then we'll just say user not found and send a 44 status code but if the user is found we'll just return it just like this okay so now if I try to send this request it's going to say for for not found now the other option that you have is you can also do find unique or throw just like this so this will actually throw an error for you if the user was not found so if I save and if I click Send you're going to see that though even though we used find unique or throw that error that was thrown is not something that is handled by nestjs okay so you do want to keep in mind of that so hopefully this makes sense so now I'll show you how we can update our users so inside my user service class I'll set up a method I'll call this update user by ID so we're going to need two arguments one we need the ID of the user and two we need the actual object of what the client wants to update the user user with so for example when you update a user do you want to update the username do you want to update the display name what is it that you want to update so this is going to be an object so we can actually use the Prisma autogenerated types so I'll call this data and I'll reference Prisma and there should be one for update uh user updates input just like that and if I hover over this you can see that the only two possible fields that you can update are username or display name so we'll use that update user input all right so now what we want to do first inside update user by ID is we want to search for the user and see if the user exists so we know how to search for the user so in fact I can actually just call a get user by ID so const find user equals so what I'll do now is I'll call get user by ID remember that this returns a promise so we need to await it so get user by ID and pass in the ID like that and then let me add the a keyword okay now if the user is not found we'll throw a new HTTP exception and we'll just say user not found 44 now if the user is found we also want to make sure that we are checking to see if the username that they want to update uh theirs with is that username already taken by someone else because remember the username field has a unique constraint so we need to first check to see if the data. username is defined because there's a chance that the the client is not updating the user's username so we don't have to worry about that at all but if the user name is in fact going to be updated then we need to check for that so what I'll do is I'll say if data. username if this is defined then what we'll do is we'll search for the user by the username so to do that first I'll actually just reuse this find user variable because I'm inside this scope over here so I can actually just redeclare this variable inside the scope and then what I'll do is I'll use A8 and we'll do this. Prisma user find unique we're going to search for the user by the username and then we'll do where username is equal to data. username like that so you're seeing right over here that it is complaining about uh type string or string field oper string fill update operations input is not assignable to type string I'm just going to go ahead and cast this as a string so now what we'll do is we'll check to see if the user was not found so if let's say for example if the user is found then what we'll do here is we'll actually throw an exception and we'll just say username already taken and then we'll set the status code to 400 okay so if fine user so if fine user is the F which means that the user was in fact found which means that the username is taken then we'll throw this exception I'm doing it this way so I can avoid nesting a bunch of logic so this way this will exit out of this function or this method and we can continue without nesting anything if the user was not found then what we can do is we can just update everything okay we don't have to worry about display name because we know display name is not a unique value and there's no constraint on it so at this point what I can do is I can actually just go outside of this if case because let's say for example if we're not actually trying to update the username then that means data that username will be undefined because we didn't provide a username for the field so we can actually just go ahead and call this. Prisma do user update and then we can just set where so the ID is going to be passed in over here so we know which user it is that we're trying to update and then we'll pass in data like this okay so just to go through everything if let's say we are in fact wanting to update the username then we need to perform this check right over here inside this if condition so we have to search for the user by the username that we want to use to update with if that username is taken then we're just going to throw this HTTP exception okay so that means it'll exit out of this entire method and return that as a response however if the user was not found based on that username that we're trying to use as our new username then it will not throw this error and then we'll just exit out of this if condition and then we'll just go ahead and call this method over here okay so this will ensure that we don't do it twice because I could have also just called it up top over here as well but it makes sense just leave it as one line down over here because if we're not trying to update the username then data will only have let's say display name then we're only going to just update display name and we don't have to worry about username being modified at all so hopefully that makes sense so now we need to go into our controller layer so inside users. controller. TS we're going to go ahead and set up a patch request and we need a route parameter which is going to be the user's ID it's going to look very similar to get user by ID so let me just copy this part and I'm going to call the method update user by ID and pass in this right over here okay now what I'm going to do is I'm going to go ahead and call this user service. update user by ID and we need to pass in two arguments remember we need the ID as well as the actual update user object itself which is going to contain the username or the display name or both so in this case we should also set up a dto for this similar to what we did for the Post request instead of using the Prisma autogenerated types you should only use the Prisma auto autogenerated types for the service layer only not for the control layer because remember what I said earlier if you use the Prisma autogenerated types in the control ler it's actually not going to take care of the validation for you okay so let's go ahead and create a dto called update user.to dots and it's going to look very similar to create user dto I'm going to change this to update user dto only difference is that instead of uh username being required we're going to mark it as optional and same thing we also want to make sure that it is a string and then same thing for display name and username should also have a question mark in front of it as well so that way both username and display name are optional okay so this is our update user dto so let's go over here and let's do app body and then update user dto and we'll type annotated with our update user dto class just like that and now we'll pass in update user Toto as an argument and there are no issues with typescript whatsoever okay and I'll just return this call all right so let's go ahead and make a patch request so I'm going to try to update the user of ID3 so the username is Anon one let's update it to Anon 2 so we're going to pass three as the route parameter and for the username I'm going to set it to Anon 2 2 and I'll leave display name alone and now I can see that the username was in fact updated to Anson 2 if I go ahead and try to retrieve that user by the ID the username was in fact updated correctly now if I try to update it to Anson a username that is already taken it's going to go ahead and give us back this 400 status code and remember that is being thrown right over here if the user was found by the username that means that the username is already taken by someone else so we throw the error okay so hopefully that makes sense so I'm going to update it to Anon 5 and that works let's just update the display name and not the username okay and send the developer to fifth there we go and let's get all the users and you can see that everything is working as expected okay so hopefully that makes sense sense now one quick thing that I did want to show you all so let's just say if I did choose to use Prisma dot let me import Prisma dot let's do user create input so the same Prisma do user create input that I'm using inside the service layer right over here let's say if I did choose to use this to type annotate the dto okay so you're going to see that if I try to make a post request to the users endpoint let's just pass an empty object you're going to see that it doesn't properly validate it just gives us back this 500 internal server error so it doesn't actually validate the request body for us and since it's empty it's going to go ahead and call this. users. create user with an empty object has nothing and we need the username so it's going to error out at the Prisma layer okay so of course I just wanted to show you all this and help you understand why we are using a combination of dto as well as the Prisma autogenerated inputs so hopefully that makes sense now one more thing that I want to show you is how to delete users this is going to be pretty easy so what we'll do is I'll Implement a method called delete user by ID inside the users service class and it's going to take in just one argument the ID so what I'll do is I'll search for the user to see if the user actually exists so const find user equals wait this get user by ID so I'm just going to reuse that method again so if the user is not found then we'll just throw a new exception or a new HTTP exception and we'll just say user not found and then 404 send a 44 status code if the user is found then all we need to do is just simply reference this. Prisma user delete and then you just set the wear to an object and specify the ID just like this it's the same thing that you would pass in when you're trying to find the user by the ID or the username it's it's that easy so now let's go ahead and call delete user by ID so what I'll do is inside the user controller we're going to set up a delete request so we're going to use the delete decorator which is also imported from njs common up top over here and we need the route parameter which is going to be an ID and I'll call this method delete user by ID it's going to have the same signature with the parameter the route parameter just like this so I'm going to copy and paste that and then I'll just return this. user service. delete user by ID and then pass in ID just like that so now let's try to delete our user so I'm going to delete the user of ID 3 click Send and now you can see that it was deleted and we are returning the user back if I try to delete the same user again you can see that it gives us a four if we're not found because the user doesn't exist okay you could return a 400 instead or something else maybe not 404 but just wanted to show you that if I tried to get the user you can see that I can't even get that user by the ID because it doesn't exist anymore if I try to query all users you can see you can see that we only have one user over here so now what I'm going to do is I'm going to show you how to set up one toone relationships and as well as one to many relationships so earlier we created three models okay so now now what we're going to do is we're going to relate the user model with the user setting model so the user and the user setting model are going to have a one to one relationship so what that means is the user will only have one user setting record and the user setting record will only have one user record so they kind of both point to each other and if you think about it it makes sense because in an actual application a user itself only has really one set of configuration options one settings right and that user settings that they have configured uh maybe they enabled SMS text messages they enabled email notifications they en enabled uh push notifications things like that you only really need one record for the user and that user setting will also need to depend on an actual user itself so they map one to one so how we can Define this in Prisma is actually pretty easy so so what we can do on the user side is we can go ahead and add another field I'm going to call this user setting settings or I'll call it user setting and then what I want to do is use the user setting model as a type just like this now one thing to note is that the user setting could be undefined because the user may not have settings configured just yet remember that with a one:1 relationship in in this case the user itself can live without the user setting okay but the user setting does depend on the user in this case without the user there's no user setting for that so we want to mark this as optional now it's going to complain because on the other model we need to define the inverse relation itself so for user setting what we're going to do is we're going to go ahead and reference user so I'm going to say user and then we're going to reference the user model like a type just like that and then we want to use this relation annotation just like this and then what we want to do is we also want to define a user ID on user setting just like this and this user ID is actually going to be the foreign key which is going to allow us to know who this settings belongs to okay so that's what this user ID is for and we also want to have it be an integer it has to match the data type of the user ID and then we're going to set this to be unique so now going back to relation we then want to set the fields which is going to be an array and you want to provide this user ID that we just have over here this is going to be that foreign key that goes inside the fields array over here and then we also want to add references and then here we want to make sure that we are referencing the user models ID so we just pass an ID like that okay so whatever you named the ID field for user so if you name this user ID then that is what this needs to be over here okay so hopefully this makes sense so now what we can do is let's go back to our terminal and uh I guess let me just create a new terminal and we'll type npx Prisma migrate Dev hyphen hyphen name and let's do user user settings one to one so remember every time we make a change we always want to run a migration uh so let's see what's going over here so it says a unique constraint covering the column's user ID on the table user setting will be added if there are existing duplicate values this will fail okay so that should be okay so we're going to hit yes and it's going to go ahead and do everything and it was successful so that's good so as I was saying every time you make any changes to your models you always have to run a migration and you can see over here if I go to this next migration you can see that what it does is it Alters the user setting table because we did created initially it Alters the user setting table it added this user ID column and then it created an index on that user ID and then over here we altered the user set table and added a constraint so this is just adding the foreign key constraint to that user ID field and then now what I'll do is inside my SQL Server if I actually describe the user setting schema you're going to see it has this user ID colum right over here and you can see that the key over here it says uni so let's say for example whenever I create a user I want to also create a user setting record automatically so what I can do is I can go into the user service inside our create user method and first we we definitely want to make sure we are passing in the data to actually create the user but in order to actually create that one to one relationship between the user and the user setting what we need to do is first we want to go ahead and actually pass all of the properties to configure for the user itself so for example we have username and display name we want those to definitely get assigned but for user setting though we want to set this property like this so this is going to map to an object and this object has this create property right over here and this create property is an object and match to an object and and this is where you're going to actually set the properties for that relation so if I try to reference the fields for a user setting record so I can reference notifications and SMS enabled or notifications on so first let's set SMS enabled to true and notifications on to false so what this will do is this will first create the user record and then it'll create a user setting record as well and then relate the two records so let's go ahead and try this out so what I'll do is I'll go to my thunder client I'll make a post request and let's set the username let's do Jack click Send so now you'll see that I can go ahead and create the new user now currently when we retrieve the response back it doesn't show that user settings relation but we can modify that however what I want to show you is if I go into my SQL Server right now in the shell and if I do select from user and then select from user setting you're going to see now inside the user setting table you can see that we have our first record and we have both columns notifications on and SMS enabled so remember how earlier notifications on we set to false by default and then SMS enabled we set to true so zero means false and then one means true in SQL this is a tiny in so one or zero and then you can see that the user ID it maps to the user ID of four so this is the for in key that points to the ID of four in the user table so ID of four is Jack so we know that this record belongs to Jack okay so now what we want to do is we want want to go ahead and actually include the relation whenever we query the users endpoint so right now if I try to get a list of users I can't see that user setting relation so let's go ahead and modify that so inside our get users method in our users service class we're going to go ahead and pass an object into find many and in this object we want to set this include property which is an object and this is where we can specify which relations we want to actually include when we query the users so I'm going to set user setting just like this and you can set this to a bleen just like this so now if I try to get a list of the users it's going to go ahead and select the user as well as the user setting relation and you can see down over here that the user setting relation has the user ID the SMS enabled field notifications on field as well as the ID the primary key of the user setting record itself you can do the same thing for get user by ID as well where I'm calling find unique so for example right now if I try to get the user of id4 this will not include that relation of user setting but we can easily modify that so in this same object I can set include just like this and then I can pass in user setting pass in that property and I can set it a true which would give me all of the relations the relation and all of its Fields but let's say if I only wanted specific Fields let's say I only cared about notifications on an SMS enabled so what I could do is instead of just setting user setting to true I can actually set this to an object and use select to basically handpick what Fields I want to include so let's say say I only cared about SMS enabled set this true and then notifications on set this true by setting to true you're just basically saying okay I want to actually include these fields okay and if you don't specify which Fields you want then they're not going to be included so by me omitting ID and user ID from here it's not going to be included so if I try to make the request you're going to see now I don't have user ID or the ID field on the user setting relation okay so this is very useful actually when you only want certain fields to be selected and also if you're using something like graphql it makes it very easy for you to only handpick the fields that you actually want I'll show you one example where we can update the users settings by the user ID so let's go ahead and set up a patch request and this will have the path of settings and then we'll call the method update user settings by user ID so we're going to need the route parameter of course so let's do this I'm actually going to do colon id/ settings so the path would look like patch users and then ID settings okay and this is obviously useful if you have an application where you want the user to be able to let's say turn on and off certain settings so for example if we wanted the user to disable SMS texts or uh enable notifications then this is what it translates to in a realistic application so we're going to grab the route parameter so let me just copy this part because the same exact thing we're going to get the route parameter and then we also need a dto to represent the settings that the user is trying to use to to update so let's go over to let's see let's create a new dto let's call this update user settings. D.S so we create a class call it update user settings dto and we only need two Fields because we only have two settings so we only need notifications on an SMS enabled and both of these will be optional so SMS enabled this is a boole and then notifications on this is also going to be a boole let's make sure we use our class validator decorator so let's do is optional and I think there should be one called is boine yep is Bine just like that and then we'll do the same thing for notifications on and let me also Mark these fields as optional uh using the question mark okay so I think that's it for the update user settings dto so let's exit out of this file and let's go back to the controller so let's go ahead and set up the request body so we're going to use the body decorator and we'll call the argument update user settings dtl type annotate with update user settings DT just like that and then now we just need to go ahead and uh call a method in the user service layer again I would recommend you have a separate user settings module where you have a user settings controller and a user settings service because you want to keep these things separate but just to keep things simple we'll use the same user service to handle this so inside the user service class I'll set up a method called update user settings and it's going to need the ID of the user so let me actually name this user ID instead just so that way we are not confused between the user ID as well as the settings ID and then the settings data I'll actually call it data instead and this time I'm going to use the Prisma autogenerated types so Prisma Dot and remember that whenever you have any models in your schema the Prisma file their types will be autogenerated for you when you run Prisma generate okay so in this situation over here because right now our type that we're working with is user setting so there's this Prisma do user setting so the name of the model and then since we want to update user setting we really actually uh don't want to have create input because this is for creating so there should actually be one for up update I believe yep user setting update input right over here and you can see that it has all of these fields that are optional so notifications on SMS enabled user so let's go ahead and leave it like this and now what we'll do is this so inside this method we want to First search for the user by the ID so we can reuse our get user by the method in this situation though um I do want to make sure that I am selecting the user setting relation because if the user does not have settings enabled then they cannot update it but you can choose to also create the user settings if they don't have settings enabled but it's totally up to you on how you want to implement this so that I'm just bringing this up right now but what I'll do is first let's search for the user and we need to use async and A8 so 8 this.get user by ID passing the user ID just like that and what I'll do is if the user does not exist then we'll throw a new HTTP exception user not found and then send a 44 let's see if the user does not have settings enabled again like I said you can choose to just create it manually so if find user. settings or user setting is undefined then you can choose what you want to do either create the settings or just throw in error it's up to you but uh typically they should have user settings because we are creating it by default so what I'll do is I'll actually just throw an error and I'll throw an exception and I'll just say uh I'll just say bad request okay so we handled these two cases so now we know that the user has found and user settings is in fact populated it's defined so we can go ahead and update the user settings so what we can do do is we can reference this. Prisma do user setting instead of user and then what we can do is we can call update okay and now this is going to be a little bit tricky because remember we don't have the user setting ID we have the user ID so what we can do is we can set where and we can pass an user ID like this okay so we're searching for the user setting by the user ID remember that user setting record let me go back to the table over here remember the user setting table it has this user ID which is a foreign key so we're basically searching for the user by the user ID the forign key itself okay and because there is a one to one relationship there shouldn't be any duplicates in this table where there's two records with the user ID of four in this case Okay because it's a onetoone relationship so we'll search for the user by the ID and then then for the data this is just going to be whatever this data argument is which is user setting up theate input so that's basically going to contain the notifications on and SMS enabled property so this will update the user setting and we can just easily return this just like that and then we're done so let's go ahead and go back to our user controller and let's go ahead and call this. user service. update user user settings pass the user ID as well as the user settings dto just like this and now let's go ahead and make a patch request to this endpoint so what I want to do is I'll try to test it out with the user of id1 first so I'll make a patch request to users one settings and this should return an error or it should return a status code of 400 because user settings is null so if I click Send you're going to see it says bad re Quest and that is coming from the service layer right over here because we don't have a user setting to find okay I can also change this to no settings like that and then it would say this again like I said I would recommend you guys to actually create the user settings in a situation like this so you could probably just do what I am doing earlier so you would just call this. Prisma do user setting create and just pass an SMS enabled and notifications on so now let's go ahead and try to update the other user so I think the idea was four and let's go ahead and do this so for the user of ID 4 they have notifications disabled and SMS enabled so what we'll do is we'll set SMS enabled to false and we'll just configure this one click Send and now you can see that SMS need is now false and notifications on is false and if I try to select the user setting again from my SQL you can see that it's now being properly updated in the database table let's go ahead and enable both so notifications on set this to true and now they're both set to true and if I try to query the user with id4 you can see that both of their settings are set to true so that's good so shows you how to update the actual individual relation itself so now what I'll do is I'll show you how we can define a one to many and many to one relationship between the user and our post model that we had created earlier so let's say for example you're building some kind of blogging platform where users can create posts and they can create as many posts as they want but each post will only have one author or one user that creat created at most okay so this is known as a one to many many to one relationship because the user can have as many posts as they want and the post will only belong to one single user okay in some situations where you have a post that can belong to many users so maybe you have multiple authors that create a post that would be known as a many to many relationship between the user and the post so to define the on to many and many to one relationship what we want to do is first for the user model we're going to go ahead and set this posts field just like this and the type is going to be post and then square bracket and all this means is that it is a one to many relationship okay then we have to go to the Post model and then we have to define the relationship the opposite side okay so for the Post we have to go ahead and set up the user field so you can call this whatever you want want you can call it user you can call it author whatever you prefer I'm just going to call it user and the type will be user just like this I also want to make sure that I set up the user ID field as well which is going to be an integer and again remember this user ID field will be a foreign key and that foreign key is basically just going to be the ID of the user itself so that way we know who this post belongs to which user this post belongs to so we're not done yet where we have our user field being defined in our post model we need to also use the relation annotation just like this and it's going to look very similar when we defined our oneto one relationship okay so inside the relation annotation we want to set this Fields property which is going to be an array and you want to pass in this user ID field that you just Define for post so user ID just like that and then you also want to set the references array right over here and this needs to point to the ID of the user itself so this ID field right over here so I'm just going to go ahead and put ID and now you can see that the linting error goes away so that is good all right so now that we are done with setting up our one to many and many to one relationship what we need to do is let's go back into our terminal so let's go into our terminal and I'm going to go ahead and run the same command npx Prisma migrate Dev and then hyphen hyphen name and I'll just call this init user post one [Music] to many all right so this ranom migration it applied it and let's see it says operation not permitted so yeah I think the reason why it failed was because we had our application running it was a permission issue so let's go ahead and try again because I just closed the application so what I'll do is I should be able to rerun the same migration based on the name so the name was in it user post one to men so let's try this npx Prisma migr Dev hyph name in it user post one too many all right there you go so now it seems like everything uh worked and there were no issues so to verify let's go back into our my SQL session right over here and what I'll do is let's describe the post table and you can now see that we do in fact have the user ID field so that's good and um yeah okay that's good so it seems like everything is good so seems like that worked let's run our application again make sure there's no issues going on okay wonderful all right so now let's go ahead and try to create an actual post based on the user itself so what we can do is let's go inside our post controller so I set this up earlier as I mentioned so this will be the posts end point where we will create posts on behalf of the user and of course we need to know who the user is now in this case we don't have authentication set up we don't have passport or we don't have any J WTS so I'm just going to have the ID being passed in the route parameter but of course if you have authentication set up then you should know how to figure out who the user is so if you're using passportjs with sessions then you'll know that the user object is attached to the request object so that's how you can know who the user is and that's how you can get the user ID so in this case like I said I'll just use the route parameter so let's set up a post request and what we'll do is this I'm not going to use the route parameter I'm actually just going to use uh the request body to include the user ID instead cuz I think it would be weird having it in the route parameter anyways so we'll create this method called create post and we need a dto for the post for for creating the post so let's create new folder it's called dto so inside the post folder we created the dto folder and now what I'll do is I'll create a new file and I'll call this create post. D.S and this will be a class called create post dto and we need a title description so let's go ahead and do that first so title string description string both of these are going to be required and then we need the user ID which is going to be a number let's go ahead and use our class validator decorators so let's do is string is not empty you can also set a Max Title on this as well max length a max length for the title so you could do something like max length of 200 characters or I'll do yeah we'll leave like 200 for now and then we'll do the same thing for description for the max length we'll just do we we'll not set max length for that and then for user ID is number is not empty okay so now let's go into our post controller and we'll go ahead and first apply the pipe for validation so use pipes validation pipe both of which are imported from njs common and then we'll use the at body decorator and the name of the argument will be create post dtl type annotate that with create post dtl so we also need to inject our post service into the post controller so let's do that very quickly so let's do private Post Service Post Service okay and keep in mind that again all of these controllers and services are already configured with the post module and the post post module is already imported into the app module okay so let's go ahead and now we want to go ahead and call the post service so the post service will have a method that we need to implement it'll just be called create post and we'll just take in this create post dtto object so now we can go into our post service class and we need to First inject the Prisma service into post service but we need to also make sure inside our post module that we have the Prisma module imported so I'm going to go ahead and add this Imports property inside the object for module and then we're going to go ahead and import Prisma module just like that and then add it inside the Imports array so now we can go into post service and we can just inject the Prisma service into our post service class just like this so let's go ahead and Implement that create post method so create post and for the arguments it is going to be Prisma we need to import that from Prisma client and then now since we're dealing with posts we're going to go ahead and reference the generated post types for a post model so since we're creating a post it would be post create input just like this post create input so similar to how when we were creating our users we had user create input for post we have post create input so it's always the name of the model and then create input that's the generated types from prismo so we want to create the post so what we want to do is we want to reference this. Prisma dopost and then call create and then for the data keep in mind that the data over here is going to require the title the description and then now for this situation we want to make sure we provide the user ID here so that way we know which user this post belongs to so luckily our dto right over here has all of these exact Fields Title description and user ID so we can use it so we don't have to obviously type out all of this we can just pass data like that or like this so now let's go ahead and just return this call and let's take a look at our controller so you can see over here it is giving us this linting issue so the reason why this is happening is because we are trying to pass this object the create POS dto and we don't have this user property because post create input expects the user property to be present so there's obviously an issue going on over here so there's a few ways that we can address this so for example the easiest thing that we could do is instead of type annotating data with Prisma poost create input we could just type annotated with the dto but there's also this other generated type for post called post create without user input and the name of it is pretty self-explanatory it just pretty much has the same exact input without the user field itself if you hover over it now you can see the type definition only has two properties title and description and optionally you can actually provide user ID for the data so I think the best thing to do is for the data itself we should only pass the title and description for the first argument and then the user ID as a second argument okay so for example let's do this let's go ahead inside our controller where I have my create post method declared over here and defined I'm going to go ahead and destructure the user ID and destructure everything else I'm going to call it create post post data instead and then in the posts service create post method I'm going to change the signature of this method I'm going to go ahead and first pass the user ID and then I'll pass the data so let's go ahead and do that so let's remove this do user ID so let's go ahead and pass user ID and then create post data just like this and inside our create post method for Post Service what we'll do is we still need set this data property so you can see that it still expects title description but user or user ID are both optional so what I'll do is I'll destructure all of data so everything that is inside this data object which only has two properties title and description and then we'll set the user ID like this and now the error will go away and we should be able to create a post now so let's go ahead and try so I have this post request set up already so I have my title I have my description and I have my user ID set to the ID of four so let's click Send and now you can see we have our first post and it has our user ID right over here and I can keep creating as many posts I want for this user let's say if I pass an invalid user ID you're going to see it says status code 500 so likely an error happened on the back end because that user does not exist but if I try to pass user ID one because there is in fact a user with an ID of one you're going to see it just works just fine okay let's go ahead and get the users again you can see we still only have two users so now let's go ahead and modify our user service we want to be able to get the users posts as well so we can go to get user by ID and then where we have our include property set we can go ahead and do posts and set this to true so this would give me all of the posts as well whenever I query the user by the ID so watch this if I try to get the user of ID one I not only get the user itself but I also get the user setting which is null and I get all of the users posts just like that and again you can of course create your own endpoint to retrieve the user posts so you can create something like users uh one and then SL posts and then have the post service take care of getting all the posts for the user so now I will show you how to deal with many to many relationships and set them up using Prisma so what we'll do is I'll actually create a completely separate model that is different from post cuz I don't want to reuse this because I'm concerned that it might possibly break our data and I just want to do this for the sake of demonstration and keep it simple so I'll create a new model and I'll call this group post just like this so this group post will have multiple users as the author so sometimes you might have some kind of article some kind of blog post that can be collaborated with multiple people so in this situ situation you would have a user having many group posts and then the group post would have many users so this is known as a many to many relationship for the group post we're going to need a primary key so let's set that up let's set up a title and then a description we'll keep it like this for now now to represent a many to many relationship between the user and group post we need to actually create another model and this model actually would translate to a junction table in the database in SQL so we're going to go ahead and call this user on group posts just like this so this user on group posts would be a junction table in the SQL database and the junction table really all that is it's basically just a table that contains the primary key Columns of the two tables that we're trying to relate with each other so for example we're trying to relate user and group post with a many to many relationship so this user on group posts Junction table will have both the user and the group posts primary keys so that way we know which user belongs to the group post and which group post belongs to the user so hopefully that makes sense so to set up this user on groups posts model what we need to do is first we need to have our user defined as a field so it's going to look like this user user and I'll get to the annotations in just a second we need the user ID which is an integer and then we need the group post itself so group post of type group post just like that and then group post ID int and now let's get to the annotations so for the user field we want to use the relation annotation and we want to set fields to point2 user ID and then for references this will have to point to the ID of the user model so just ID just like that okay and then now we'll set up the relation for group post so it's going to be very similar so Fields this will point to group post ID and it references whoops and then it references the ID of group post model just like that okay so we created this model that represents a junction table and the last thing that we do need to do though inside this model is we need to use this double at ID and this double at ID is also another attribute and all this means is it just defines a multi-field ID of this model so you need this for the junction table so what we want to do is we want to pass in an array and we want to contain both of the IDS for user and group host we have the user ID right over here so we want to reference this user ID and then group post ID right over here so now that we're done with this model let's go to the user model first and we want to define the relation on the user model side so we'll go ahead and set the field for user we'll go ahead and do group posts and this will be user on group posts like this with the square brackets at the end then we'll do the same thing for the group post model but it will be users instead and then user on group post like that and that's it we're done so now let's go ahead and run the migration so let's go to our terminal I'll make sure I terminate the application process and let's type npx Prisma migrate Dev I I name inet and I'll just call this many to many just keep it simple and let's make sure everything was done successfully so seems like everything worked and that's good so let's close the terminal and let's go ahead and take a look at the migration. SQL file that was created so you can see what's going on so first it created the group post table because we didn't have that then it created this user on group post table and again this is the junction table right over here and you'll notice how it has two primary keys this time user ID and group post ID and then down over here you can see that on the same table they added a foreign key on user ID which references the ID of the user and did the same thing for the group post ID as well okay so again you'll better understand this once we actually start to populate the data in our database and you'll see how that data will look like in the form of a table all right so now that we have this all set up we can go ahead and actually begin creating group posts so just to keep things simple again I'll reuse the same post controller so this time what we'll do is we'll create a single group post and then we'll have it assigned to two users okay so let's go ahead and do this uh let's do at posts or at post and then we'll do group so the way that this endpoint will look like is post posts Group which means this will be a group post we'll do create group post as the name of the method and we will need a request body okay so let's go ahead and create a new dto create group post. D.S and it's going to look very similar to our create post dto right over here uh the only difference really let me just make sure that title and description are the same okay uh let's see yep it is title and description are the same that's good okay wonderful so the only difference is instead of just having one single user ID we're going to actually have an array of user IDs this time the way that validation is going to work is is going to be a little bit different because we're validating an array and not just a single scaler value so what I can do is for the is number decorator it takes into arguments take in is number options and also validation options both of which are optional so I I really only need validation options which is the second argument so I'll just pass an empty object for the first one and then for validation options the second object I'm going to go ahead and set this each property to true and this will ensure that it validates each value in the array if user ID isn't the right which it is okay so this will ensure that every single element in user ID is a number we'll do the same thing for is not empty but is not empty only takes in one object one argument which is validation options so we'll set each to true as well additionally I also want to make sure that the value for user ID is an array so I can use the is array decorator to make sure that it is in fact an array so let's go into our post controller and first let's apply the validation pipe on create group group post and then now let's go ahead and extract the request body so create group post dto and then type annotate it with create group post dto just like that so let's just test out our endpoint make sure that it works so I'll go ahead and make a post request to posts SLG group just like that and we'll pass over request body and now it's going to go ahead and validate everything for us so title and description as well as user ID are all missing so let's do Hello World description let's just do the same thing hello world and then let's also see what happens if I don't pass user ID you can see that user ID must be an array so user ID now the other problem is that I could also pass in an empty array so let's actually fix this let's make sure that it is not empty so there's a decorator called array not empty so I can do array not empty just like that so this will ensure that the user ID array is not empty so if I go over here if I click Send now it says user ID user ID should not be empty so that's good so we have everything properly validated okay so now you can see that if I pass in a value for the user ID array it works so let's go ahead and go into our posts service class so we're going to implement the method where we're going to create a group post okay again like I said we're going to use this same posts service but ideally you would want to create a separate module to handle a different domain because a group post is different than a regular post so I'll go ahead and create a method called create group post just like this and what we're going to do is we're going to reference this. Prisma do group post just like this okay so we're going to create a group post regularly just like this call create method and the data is going to be pretty much the same thing as a regular post right it's going to have title it's going to have description but then we want to also make sure we have all of the users the user IDs that are are mapped to the group post okay so that way we know which users have contributed to this group post so what we can do in this situation is there's this property remember we have this users property over here okay and this is going to map to an object and we can use this create property and this is actually going to be an array this time okay you'll notice that this is really similar to earlier when we were creating a onetoone relationship between the user and user setting remember how we used create but this was an object because that was only one to one but this time we have multiple users that we want to create for this group post well not create the users but kind of like connect the user to the group post itself so inside this array for create we would pass in the actual user ID so just like this we'd pass in the user ID just like that so this would create the group post and then relate it to the user of ID one and if you had other users you would pass them as as well like this okay so I just want to show you the structure of how it's going to look like but let's go ahead and just remove all of this remove this as well and let's take in the arguments for create group post so this is going to be a little bit tricky okay because for example if we were to use the Prisma autogenerated type so there should be one for group post let's see create group or group post create input and we look at the the type definition you can see that we have title descriptions and then the users would be user on group post create n manyu without group post input so this itself seems a little bit sophisticated so what I'm going to do is is this we'll do group post without users input so we'll just have the title and description and we'll pass the user ID separate so first let me do this I'll do user IDs which is going to be an array of numbers and we'll pass in the data which is only going to contain the title and description so it's going to be similar to what we did earlier with creating a single post for a regular for just one user so the way that this is going to work is for data I'm going to go ahead and use the spreader operator on the data object itself so this will unpack all of the fields inside the object so title and description and then we're going to go ahead and set users just like this to be an object and set create and then what I'm going to do is because I know that this is an array I'm going to reference user IDs map so I'm going to take each ID and put it in an object so I'm transforming this user ID's array of numbers into an array of objects that has a property called user ID okay because remember the array takes an object or it contains objects that have this user ID property okay so we're going to go ahead and do user IDs map and then for each user ID we're just going to return the user ID okay so the user ID property maps to the user ID value itself so do it shorthand would look like this so let's go ahead and return this call and now we'll go ahead and go into our create group post method inside post controller and we'll just do return this. poost service. creat group post we'll first pass in the user IDs so let me go ahead and the structure user ID I should have also I should have named this user ID let me fix that real quick user IDs with an S so user IDs and then the group post data and then we'll pass in user IDs and then create group post data and there's no issues with this so let's go back to our Thunder client let me change this to user IDs and if I try to send this it's going to say user ID should not be empty so that's good so I know that there are two users I have a user of ID 1 and of ID 4 so let's pass one for now and let's see what happens okay so it created this post so let's go ahead and take a look at our tables so let's take a look at group post first select from group post so you can see I have my group post let's take a look at user on group post table and let's see what that looks like you can see that inside the user on group post table and remember this is the junction table that I was talking about that has a combination of all of our uh primary keys for user ID and group post ID so what this tells me right over here is that the group post of id1 has only one user of ID one okay so this group post although this is a group post it only has one user or one author so now let's create another post let's add two users this time let's do one in four and now you can see I have my post created but let's go ahead and select that user on group post Junction table again and now you can see that it added two new records to this table so if you look right over here we have a group post ID of two and you can see that right over here it has user ID of one and then on the next record it has group post ID of two and then user ID of four so what this tells me is that on the group post with an ID of two it has two users that this group post belongs to okay so now this is how the many to many relationship looks like you have a user that has many group posts and the group post has many users okay so let's just very quickly set up an end point to get all the group posts so let's do this let's set up a get request I need to import The Decorator so let's do that and we'll do group so this will be get posts group and then we'll call this method get group posts and this will call a method this do posts service do get group posts so we need to implement that method in the post service class so let's do that so get group posts we're going to go ahead and return this. Prisma so now we want to get all the group posts so we'll do group post. find many and let's see what happens if I try to make a get request do this so you can see that I have all of my group posts but it does not show the users so let's go ahead and make sure we do that so inside our post service class inside get group posts inside the find menu call we're going to pass in this object and remember we want to include the relation so we want to include users set this to true and let's take a look at what the data will look like so notice how now if I click send you can see that over here we have this users which is an array and and you can see that it has this user ID of one group post ID one and over here it has user ID one and then user ID 4 okay so this looks a little bit weird because it h it's actually getting the data from The Junction table itself so we'll replace this value of true we'll map it to we'll map users to an object and we'll do this we'll do select and let's just select the user because what it's doing is it's selecting group post ID that's why over here you're seeing the group post ID and the user ID but let's select the user itself and let's see what happens so if I click Send now you can see that let me zoom out a little bit you can see that for each group post I have the array of users and this is an actual user object itself okay you have this array and then in each object it has this user property and then it has this user record over here which has the ID username and display name down over here we have the same thing though we have two users this time so we have the user and then we have let's see Anson and then Jack okay so this is how you can handle many to many relationships for your application so that is going to be pretty much it for this video I wanted to make sure we covered all of the basic crud functionalities using Charisma how to create data how to read data from the database update data as well as deleting data then I also wanted to make sure I showed you all how to handle on toone relationships one to many many to one relationships as well as many to many relationships so I hope you all enjoy this video If you like this video definitely leave a like down below if you have any questions feel free to join the Discord server the link is in the description and comment down below what you would like to see in future videos on this channel so thank you so much and I will see you all in my next video peace out
Info
Channel: Anson the Developer
Views: 2,784
Rating: undefined out of 5
Keywords: nestjs, prisma, mysql, nestjs prisma
Id: uWZ_6pDbLpU
Channel Id: undefined
Length: 103min 55sec (6235 seconds)
Published: Fri Jan 26 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.