Learn Prisma In 60 Minutes

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
this is one of the most comprehensive videos i've ever created as you can see by the huge amount of notes i took for this video i spent over a week reading the prisma documentation playing around with examples and distilling down the most important topics that way i could include everything you need to know in this one single video and even though this is a longer video it includes everything you need to know about prisma so you won't need to use any other resources other than this i also have tons of timestamps in this video so you can jump around to the particular parts you care about or come back and use this as a reference in the future with that said let's get started [Music] welcome back to web dev simplified my name is kyle and my job is to simplify the web for you so you can start building your dream project sooner and we're going to be talking all about prisma in this video now you are going to need to have nodejs installed in order to follow along with this tutorial i have a video covering how to install it i'll link in the cards in description for you and you're also going to need to have some type of database installed or a database on a server somewhere i'm going to be using postgres for this tutorial but you can use pretty much any database you want just know that if you use mongodb or another nosql database some things may be slightly different and that's because prisma's generally built for you know sql databases but you can use it with something like mongodb if you want now to get started with prisma what you're going to need to do is you're going to need to download all the dependencies for the project before we can download our dependencies though we first need to initialize npm by typing npm init y that's going to give us a package json file and then we can install our dependencies so we can just type in here save dev and that's because every dependency we need for this project is a development dependency so we need to have prisma itself so we can type in prisma we need typescript and that's because prisma is built on top of typescript you technically don't need typescript but we're going to be using in this project we have ts node which gives you typescript definitions for node and we're also going to have here at types slash node and that again is helping us with our types in node and then finally we're going to be using nodemon which allows us to refresh our server every single time we make changes so if we make changes to our file we can click save and it's going to rerun that code for us automatically which is really handy now as soon as this is done installing then what we need to do is actually create a ts config file so i can just come over here type in tsconfig.json and this is going to be a file that contains all of our typescript configuration and inside the prisma documentation it tells you exactly what you should type in here i'm just going to copy this over and this is the documentation that is recommended by prisma for your ts config now if you want you can go to the prisma documentation which i'll link in the description and it may have slightly different rules but you can really play around with these rules or use a typescript config that you already have in your project it really doesn't matter now once we have all those dependencies installed and this ts config file created what we need to do next is actually initialize prisma so we type in npx prisma init that'll initialize like prisma and the schemas and migrations all of that for us but we can also tell it what database we're using by typing in dash dash data source oops dash provider and then just type in your database in our case we're using postgres so we can type in postgresql hit enter and that's going to initialize some basic files for us and it's going to use postgres by default so if we open up this prisma folder that's what's were created you can see we have the schema.prisma and inside of here we have just really basic code this is going to be your schema file i'll talk a little bit about but you can see we have a generator and we have a data source also we have this dot env file which contains our postgres url this is going to be the url to whatever database you're using so you would need to type in your own specific url here and also we have a git ignore that just contains that env variable and this node modules just to make sure none of this goes into our github repository now one other thing to note if we go back to this prisma file is you'll notice i have really nice code formatting in here and code highlighting that's because i have an extension installed called the prisma extension if you just type prisma in this is the extension you want to look for it's going to give you syntax highlighting and code formatting so if i come into that file let's just go back to it real quick and i just make some changes like i add a bunch of you know tabs in here for example and i click save it's going to automatically format my code for me and that's because i have auto formatting set up inside vs code but if for example you didn't have auto formatting setup so if i just go into my settings we'll just come in here preferences settings and i just type in format oops format actually i think i need to go edit my settings as json here and if i find prisma you can see here prisma i have my default formatter set to the prisma formatter and i have it set to format on save if i comment this out and i go back to my prisma file and i make changes and i save you can see it does an auto format but prisma has a formatter built in where you can type in npx prisma format hit enter and that's going to format your schema file for you automatically so you can do both ways of doing this i obviously prefer to have it inside my settings which is why i have it auto format on save just like this so that way when i make those changes click save it automatically formats and i don't need to run that code in the console now very briefly i want to explain a little bit about what this generator and this data source is before i continue going on in this tutorial and essentially the generator is what your code is generated into because this right here is a schema file you're going to define a bunch of code for your database in this prisma format it's not sql it's not nosql it's the own format of prisma it's completely separate from any other type of you know sql formatting you would think of so you're going to define your code inside this prisma specific format and then when you run your generator what are you going to generate your code into in our case we're generating this prisma client js and this is just the default we're saying hey take all this prisma code and convert it using the prisma client js formatter which is the default generator that we care about and this is what 99 of your projects are going to use but let's say you're creating like a graphql api there are actually different generators you can use that generate a bunch of graphql api code for you automatically based on your schema so if you want to have an extra step an extra layer added for that graphql you can do that with a generator for our example and everything in this video we're going to be using the default generator because that's what you're going to use 99 of the time now data source this is pretty self-explanatory and here we have our provider which is just where our data is coming from in our case we have postgres you could use mysql you could use mongodb whatever you want and then we have the url which is defined in our environment variable right here now this url you actually need to make it your actual url and in my case our url here has a user of postgres the password is just password and then this is 5433 and our database here we're just going to call test you can call the database whatever you want we're just going to be using a database called test now it is important to note that whatever database name you use that database must already exist i already have a database on my computer called test it's just completely empty and that's what we're using for this project now back to that schema file that we have here that dot prisma file the next thing we want to do is actually define our schema and the schema just represents like all of your different data and we're going to define the most basic schema at first just to get something started before we start diving into the more complex intricacies of the schema so we want to create a model and you just type in model and then give it a name in our case we'll create a user model so we have a model called user and inside these curly brackets is going to be all of the code for our model and you can already see we have syntax highlighting saying hey you know what our model doesn't contain an id and every single model inside of prisma must have some form of id so let's create an id and we're going to make this id an integer so we're going to type in int right here and we're going to define that it is an id by putting this at symbol right here now all of this syntax is fairly confusing to get started with we're going to deep dive into exactly how this works but first i want to just define the most basic model that way we can see the whole top to bottom workflow of prisma before we dive deep into each individual section and the last thing i want to do is define a default value and this default value i just want to auto increment and you can see that we have awesome code syntax suggestions based on this prisma extension which makes working in the prism environment so easy so we have a user that has an id and we're going to give it a name which is a string now when i click save you can see everything auto formats for me and this looks really good we now have a user model that's defined in our schema with an id and a name super basic stuff and that's all we're going to do to start here now by defining this model right here we haven't actually done anything with our database prisma and our database are completely separate from one another they are able to interact with each other but by defining something in prisma it doesn't actually do anything to our database what we need to do is we need to tell prisma hey you know what i'm done making changes to my schema can you apply them to my database i want you to migrate my changes from what i had before which was nothing i want you to add this new model to my database to do that we need to run a command this command is called npx prisma migrate and then you can optionally pass in a name as well and we also want to specify that this is for development only so we type in dev here and that means we're going to be pushing a migration that is in our development environment and we're going to give it a name of knit because we're initializing our database with this new model of user we click enter and it's going to run through a bunch of code essentially it's going to create a brand new migration file and that migration file is going to be able to interact with our postgres database and make all of these changes and you can see right now it just did that your database is now synced with your migration here and we have this migrations folder if i open it up you can see inside of here we have a sql file that contains our migration which just says hey create us a table it's called user give it an id and a name and a primary key of id which auto increments really basic stuff you'll also see something really important here it says generated prismaclient and it says it put it in my node modules folder at prismaslash client essentially we have created a brand new prisma client and this client is that thing from the generator we're saying hey create me a prismaclient js whenever i change all my code and i make changes to my database such as adding this model i want you to update my client code which in our case is this prismaclient and that's what it does every time you make a migration it's going to update your client for you and that client is essentially all of the code for interacting with your database now that we've added this user model our client added a bunch of code automatically for us that allows us to interact with users create them read them update delete them and so on and all of it is typed with typestrip so we have this nice type safety blanket now unfortunately we don't actually have a client yet because we haven't installed the client library so we need to do that now we can type in npmi at prisma client and this is going to install the client that allows us to actually generate and use this client and when we first install the client from doing this migration we already have everything generated but if you need to manually regenerate your client you can type in npx prisma generate and what that's going to do is it's going to go through all the steps of generating based on whatever provider we want which is the default one and you can see that now we can start using our prismaclient because it automatically generated it for us and stored it in that particular location and again that's all of our prismacode in that one place so let's just copy this little bit of code it gave us we're going to create a brand new file called script.ts and inside here i'm just going to paste that code and this allows us to access our prismaclient so now we can type in for example prisma dot and you can see we have a bunch of different methods as well as this user right here and user represents that user table we created right here it's automatically generated for us so we can say dot user and you can see we have a bunch of different methods for example we could do like a find first to get the very first user based on different criteria we pass it now i'm just going to paste in a little bit of code right here and this code is essentially just a really simple way of using async await we just created a function an async function called it main and then down here we're catching any errors and printing them out or at the very end we're finally disconnecting so as soon as we're done running all of our code we're disconnecting from the prisma database and that's something you don't have to technically do but it's probably a good idea to disconnect when you're done but it'll automatically disconnect for you as soon as your program finishes running so in our case it doesn't really matter because it would automatically disconnect but adding this in there is also just fine so now inside main here we can write any of our prisma code and the reason we put this in an async function is because almost everything in prisma is asynchronous so it's going to run it's going to wait and then it's going to give you a result so using async await makes it easier to work with and if you're unfamiliar with async await i have a full video covering it i'll link in the cards and description for you so what we can do inside of here is we can say prisma.user and let's create a brand new user we'll just say create we're going to pass in data that's how we specify what we want to create we say data and we pass it an object that contains all the data we want in our case we have a name we can say name is going to be kyle just like this now this is going to create us a brand new user and if we make sure we await this by just saying that we're going to have a user and we're going to wait right here we can console whoops console.log out our user so we're just waiting for prisma to create a user for us it's going to put it in our database with the name of kyle it's going to return that user and then we can log that user out right here so in order to run this program let's go into our package.json in our scripts section let's create a script called the dev start i'm just going to say nodemonscript.ts and that's going to automatically compile and rerun our script ts file every time we make changes so i can type in npm run dev start which is that title or that script we just created and it's going to start up ts node it's going to run and you can see it just created a brand new user named kyle with an id of one let's say we want to create sally i can come in here change the name to sally click save and now we have an idf2 with the name of sally super straightforward also if we wanted to get all the users we could just say for example find many and we can come in here and we can just say this is going to be all of our users click save and that's going to generate all of our users you can see we have our user kyle and our user sally and that right there is like the basic overview of prisma from top to bottom at the very top you create your schema and the schema defines the data source you're using so your database it defines the generator for how you go from your schema to your typescript code and it defines all of your different models and enums and everything related to your database all inside this one file then once you're done with that you create your migrations and your migrations allow you to make changes to your database based on the changes you made in this file so when you update this file it'll automatically create a migration that moves you to the next step so your database is always up to date with this file also in doing that migration you're updating your code with this generator this generator creates a library for you this prisma library right here that allows you to interact with your code through this prisma library so you don't have to write raw sql queries so this schema file essentially defines your entire database it allows you to migrate your database and it allows you to interact with your database this is like your single source of truth and is really important to understand and that's why in this next step of this tutorial i'm going to be covering everything you can do inside this schema file for prisma and it is a lot now first i want to go a bit more in depth on generators and data sources before we really dive into the complex part which is our models so when it comes to data sources you can only ever have one single data source and that's because prisma is directly connecting to your database so you can only have one database that defines all of your data so only one data source and it must have a provider which is the name of your database you're using and it must have a url which links to that particular database also it's really important that you use environment variables for storing your database url that way all of your password information is safely secure inside of this file and you can also change the database that you're using for development staging and production and so on now the next thing that we have is a generator and you can have multiple generators for example we could have a generator for our prisma client and we could have a generator for some type of graphql api there's tons of different npm libraries out there for different generators so you can take a look at them if you want but in our case we're going to be using just this one generator now in order to define a generator all you do is you give it the provider and the provider just links to the name of that generator and whatever generator you want will tell you what the code here should be for the provider name so now let's move on to the more complex part which is models models essentially represent the different tables inside your database where you can store your data and each model is essentially composed of a bunch of different fields each row you see right here is considered a field and a field is composed of four different parts the first part right here is just the name really straightforward this is our id field this is our name field we could have for example an email field just like this and that's just the very first part here is the actual name then the next thing that we have after that is going to be the type of that field so we have an integer here we have a string and so on after that we have two different things that are optional so you are required to put a name and a type on everything but optionally you can have a field modifier and you can have attributes so a field type modifier would be like saying hey you know what the name is optional so we're going to put a question mark here and that says that this name field is optional we're going to cover all the different type modifiers in a little bit but that's what those would look like and then attributes or all these things that start with the ad symbol for example we're saying this is an id field we're giving a default value those are all your different attributes and again they're optional our id field has a bunch of attributes but our name and email field do not so now let's dive into some of the different types of fields that we can have i'm going to cover every single field type that's possible so far we've covered the integer field type and the string field type but there's a ton of other field types for example let's have an is admin field and this is going to be a boolean so we just say our type right here is boolean that's going to be one more type that we can cover another type that we can cover is something called a big int for example if we had like a large number and this is a super large number that we wanted to be able to like finely tune and cover that's going to be larger than a normal integer you would want to use a big integer to represent that and we could just type in big int here we don't really have anything that would be big in related in this application so we're just going to remove that for now another type of field that you could have would be a float i'm actually going to create a new model and this model is going to be for a post and this post is going to be like a blog article that someone wrote and this blog article can have a rating so like a five star rating and this rating can be anywhere between one and five stars so maybe it's like 4.7 well we know that this is going to be a decimal value so it's going to be a float and that's because a float essentially represents a floating point number or a number that has decimal places there are also different types of floats that you can have for example you could have a float or a decimal these are both very similar in that int and big int are almost the same thing a float is kind of like a less specific it's a more general floating point number while a decimal can represent a much wider range of floating point numbers so if you need to be really accurate with your floating point numbers decimal might be the way to go otherwise for most use cases float is going to be just fine another type of field is going to be a date based field so for example we could have like a created at which is going to be a date time and we can have an updated at field which is also going to be a date time date times just represent essentially a time stamp so like a date and a time that's all they are it's the only time based type that you can use in prisma now those are most of the main data types you're going to use but there's a couple other unique ones that you might run into for example you might have like user preferences so we could say preferences and this is just going to be a json object so we can use the json data type to represent that not all databases support the json data type but postgres for example does which is why we can use this if we are using something like sqlite for example as our database you can see immediately we're getting an error that says hey json is not supported in that database so it's really nice that it takes care of that for us another type that you're going to run into is the type of bytes so we could come in here and you know we could say that we want to have like a blob and this is going to be a type of byte so like if you're storing like file data or like really big data that you need to convert down just raw byte information you could use bytes to store that a lot of times you're not going to really run into this data type that much so it's not super important another data type that you might run into is the unsupported data type this is a really interesting data type in that it is not something you're going to ever write yourself inside of a prisma schema file but prisma allows you to actually take a database that already exists and convert it to a schema file and since prisma doesn't support every single type of data type in the entire world there are going to be some that are unsupported so it'll list them as unsupported if you take an existing database convert it to prisma and it does not support that data type but if you're just starting out with prisma you're never going to use this data type at all now the last type of data that you could run into would be like data that represents another object for example if we have a post we could have an author and that author could be a user now in order to define this type of relationship data you actually need a lot more information than just writing out there's an author with the type of user so when i click save you're going to notice it's actually going to auto populate a lot of information for me you can see i click save and automatically it added this post reference inside of our user it added this user id and it added this author tab right here which has this huge relationship section this is essentially how you make different relationships inside of postgres i'm going to cover the three different types of main relationships you have you're going to have a one-to-many relationship which is where you know a post has one author and a user has many post one to many we're going to have many to many for example one post could have a category and a category could have many posts so each post has many categories and many categories have many posts so there's a many-to-many relationship there and then also i'm going to be covering what happens in a one-to-one relationship for example if a user has like a table of preferences each user has one reference in that preference table and each preference has one user it links to those are the three different types and we're going to cover all three of them here so the first one is one we've already started to cover which is a one-to-many relationship so a user is going to have many posts so let's come in here we're going to say that many post and it's going to be a post array and this array syntax right here is a field type modifier and there's only two modifiers you need to know of there's the array one which says there could be multiple of this thing and there's question mark which says it is optional those are the only two field type modifiers out there and you're going to see them all the time so we're saying each user has multiple posts and they are the type post and there's an array of them and then inside of here our post has this relationship the field right here is referencing what field inside of our post table is referencing the id inside of our user table so we're saying that the user id field in our post right here references the id field in our user and those two should be the same so whenever the user id is the same as the id that means they are linked together it's like a foreign key relationship if you're familiar with sql now in our case we want this to say author id so we can change that to author id instead of user id and now that's going to link this author id column with the id inside of our user table another thing that i want to show you is that you can use more than just auto incrementing ids you can actually use uuids as your id which is something that i find a little bit more common to use uuid instead so we can just type out uuid right here and make this a string type and move this down here as a string type and now we're going to have uuids instead of auto incremented ids and that's just going to be a little bit more secure because people can't just change the id from one to two and access new information uuids are completely random and unique also our post should have its own id so i'm just going to copy this down and we're going to give our post an id to get rid of those errors that we had now that right there covers how to do a one-to-many relationship what happens if a user can have two references to a post for example we're going to have posts that they wrote so we're going to have written posts and we're also going to have favorite posts so for example they favorited some posts so we're going to have favorite post and written post and both of those are going to be a reference to post and then down here we're going to have both a author and we're also going to have i'm just going to copy this real quick a favorite so we can say favorited by and favorited by id so now this is saying that a post can be favorited and a user can have multiple favorite posts and multiple posts that they have written but you'll notice we get an error essentially we're saying hey we can't you know validate this because it's ambiguous which one is written post which one is favorite post because they don't actually say and we just make sure we update this right here to be favorited by id these relationships both point to the post table we don't know which one of these relationships is pointed to we need to give these relationships a name so we can pass in a first property to this relationship function we just say written post name it whatever you want it doesn't matter this is just a label and this label can be shared with all of the other fields so up here we can say at relation and we can say that this is going to be a written posts and down here this is our favorite posts and our relation for this one is going to be that favorite post so what we've done by this is by giving these names is we disambiguated it we've said this written post array right here references this author and author id section while this favorite post references favorited by and favorited by id so you only need to do this extra step is if you have two references to the exact same table normally you don't have this but in our case we do have this scenario also before we move on i'm going to make this user field right here for favored by optional so i'm just going to come in here and put a question mark to say you know what our favorite to buy is optional we also need to make sure our favorited by id is also considered optional because both of those fields are linked to the same thing so that right there covers a one-to-many relationship as well as disability multiple one-to-many relationships but what happens if we have a many-to-many relationship let's say that we have another model called the category in this model category we're just going to give it an id just going to copy this id over here so we have an id and it can have multiple posts so for example say post is or sorry not equal but we can have this post array so essentially one category can reference multiple different posts and a post can have multiple different categories so we can say category array if we save you'll notice we don't need to do any fancy at relationship setups it just automatically knows that our categories right here is referencing this category model and this post right here is referencing our post model and it's automatically going to create a joining table between the two that is going to hook up all these relationships for us so all that complicated join table stuff that you would normally have to do for many dimensional relationships is taken care of by prisma and you don't need to worry about it at all so right here with this little bit of code all of our posts can have multiple categories and all of our categories can have multiple posts now the final type of relationship i want to talk about is a one-to-one relationship so we're going to say one user is going to have one set of user preferences so instead of using this json right here i'm going to bring this into its own table so we can say we're going to have a model called user preference just like that and this user preference is going to have an id so let's just paste in an id and we're also going to give it a field like email updates for example which is a boolean so we're saying hey you know what do you want to receive email updates or not that's all this is saying and now we want to reference the user table from our user preference now since we're doing a one-to-one relationship you can store the relationship on either the user table or the user preferences in our case i'm going to store it on the preferences so i could just say user is at our user table and we can also have a user id which is for that user table this is just a string if we save this you can see it automatically does a lot of that relationship for us and we don't want this to be an array though we want this to be a one relationship so we can just put a question mark here we're saying optionally this is going to have a user preference just like that and you can see here this automatically marked itself as unique because this user id must be unique the reason this must be unique is because we can only ever have a preference reference one user we can have multiple preferences referencing the same user that's how this one to one relationship works now speaking of this like at unique attribute let's actually talk about a lot of the different other types of attributes besides the relation attribute because so far we've just talked about relation id and default but there's a ton of other attributes out there and one of them is the unique attribute for example we want our emails to be unique so we can just put an ad unique on our email and now every single email is going to be unique now the last kind of attribute i want to talk about at least field based attribute is going to be the updated at attribute down here we have this updated out field and if we give it the attribute updated at what that's essentially going to say is that every time we update this post it's going to automatically set this updated at field whatever we specify is updated at as the current timestamp so it's automatically going to update that for us we don't have to worry about manually keeping track of that updated at time which is super cool also created that we should probably give it a default of now so we can just say default now and that's going to default to the exact current timestamp when we create this so that way when we create this we don't have to worry about manually setting this time now before we start talking about the last set of different attributes which are block level attributes i want to define a few additional rows to all of our different tables so for example we're going to give each one of our post a title which is going to have a string we already have our rating i'm going to change this to average rating just because it makes more sense with that float specific type we have our created a we have our updated app we have our author favorited by favorited here all that is looking really good down here in our category i want to give this a name which is a string and up inside of our user i want to give our user an age which is going to be an integer also down here i want to make this unique so we're going to say that our name is unique so that's going to be like the basic bare bones of our schema but there's something else we can do besides just these single at field level attributes we can actually do block level attributes i want to discuss a little bit the difference between the two a field level attribute applies to the field as you can see our id has the id attribute it has the default attribute they're in the same row as our field and they also have one single at symbol in front of them now a block level attribute goes inside of these curly braces and it's on its own line completely and they have two at symbols in front to represent that this is a block level attribute for example we could do inside here is we could create a block level attribute on uniqueness and we could say that inside of here we must have a uniqueness constraint on age and name we cannot have two people that have the same age and name so we could just say age name just like that and now what this single line of code right here is saying is that inside of our field we must have our agent name be unique and let me just get rid of those quotes that was an accident on my part so now we cannot have two users that have the same name and the same age we can have two users that have the same age and different names or the same name and different ages but if you have the same name and the same age it's going to throw an error because we have this uniqueness constrained we could also specify an index so i'm going to come in here and i'm going to say we're going to have an index and let's say that we want to create an index on the email field so we could have an email index and this is going to help with things like sorting and performance and we could also index on like email and name if we wanted for example but in our case we're just going to index on email because what if we want to like query by email it would be good to have an index on that now the last type of block based attribute i want to talk about is going to be the id attribute so if we come in here we can actually create an id attribute if we just comment out the id up here we can create a composite id so essentially an id that contains two different things so here our id could be an id that is on the title and it could be on the author id so now we're saying that instead of having a specific id we're saying that our title and our author id represent our id for the post so we must have a unique author and title combination and that'll be corresponding to our id instead of having this auto-generated id up here now in our case we don't actually want this so i'm going to remove this but i just want you to know that this is an option that is available now that pretty much covers 99 of everything you need to know about models there's really not much else to learn but there is one other type of you know data source generator model that we want to talk about and that is an enum so if we come down here we can create an enum and this enum we're going to call role now this role enum is going to have two values we're going to have basic and admin and right here that'll help us define how our user is is our admin or not and this is admin field let's actually just get rid of this and replace it with a role which has the type of role and by default we want them to be a basic user now we have a bunch of different roles and as we add more roles we can come in here we can say like oh we now have an editor role for example and that's just going to be defined inside of this enum and this is really nice if you know a field only has a few set values that it can be like basic admin editor if you define an enum it's going to make sure that when you actually start writing out your code it'll only allow you to specify one of those specific values instead of just any value at all so if you have a hard-coded list of values that something can be using an enum is a great way to do that so that right there covers everything you need to know i mean we covered models data sources generators enums it's everything you need to know about the prisma schema and if there's anything else that you need to know beyond that it's super niche and you're probably not going to use it very often so now that we have our entire schema written up let's actually migrate our database to include all this new information we can type in npx prisma migrate and we could say dev and if we don't give it a name we just hit enter it will just ask us to specify a name so if we just give it a second here it's going to ask us to specify a name and we can just give it any name that we want but it looks like we actually ran into an error if i scroll up here it says we found changes that cannot be executed it's trying to add the column age which is required but there's no default value and there's two rows in our table that have that value so this is nice it's doing validation for us being like hey you're trying to do something but it's not going to work so for now what i'm going to do is i'm just going to go into our script file here i'm going to delete everything so we're going to see we're going to delete all of our users because we don't actually need them it's fine we can get rid of them just to start at a clean slate npm run dev start if we just run that that should hopefully delete everything from our database and then we run our migration it'll hopefully work just fine so that ran everything and now we can do is run our migration and hopefully we should no longer have any errors because those users that we created when we're testing are no longer there and then it should ask me for a name as you can see are you sure you want to create and apply this validate this migration is just saying a unique constraint on this table will be added if there are existing duplicate values this will fail same thing here unique constraint if there's 16 values it'll fail we don't have any so it's fine enter a name we can just say test whatever you want for the name it doesn't matter and now that created our migration and generated our client for us we go into our migration folder here you can see there's our first migration and our second migration obviously this one is much larger because it essentially creates everything inside of our schema file and it's nice because all of this code is kind of cumbersome to write but the nice thing is the schema file defines it all for us so now we are finally able to move on from this prisma file and we can move into our actual javascript file and we can start talking about all the different functionality that prisma provides us and we're going to be talking about creating reading updating and deleting now first i do want to say just a few little minor things about prisma that are important to understand is that when you create this new prisma client this actually manages different connections for you so if your database supports up to like five concurrent connections this prisma client will handle all five of those connections for you so it's really important that you only use one instance of this prisma client and you don't create a bunch of them otherwise you could bog down your database with too many connections now with that said let's actually start writing out our prismacode let's create a user we've kind of already looked at the create function but let's really dive into how it works we're going to come in here we're going to create a user for some data and you can see when we auto populate we have a name and an id and it looks like our code is not actually generated so we need to rerun that generator again just to make sure everything works so let's just type in npx prisma generate to make sure that our generator works to actually generate all of our code we'll give it a second to actually run there we go so now it should hopefully have generated click control space it still hasn't generated sometimes you will run into this problem i found the best way to do this is either just close out of your file and then reopen the file back up that may fix the problem if we come in here click ctrl space you can see it still hasn't updated it the next specs option is hold down control or command if you're on a mac and just click on the function you're trying to go to and inside of here you'll hopefully see that it actually opened up a typescript file and this typescript file contains all that information when it opens that up it's going to reload all your typescript and now you hit control space you can see all of our information is there so for some reason generating it doesn't actually fix it for you just try those steps and it should hopefully auto populate worst case scenario just close vs code reopen it and it'll definitely work and since you don't run migrations very often it's okay that this is a little bit cumbersome so as you can see based on this our age name and email are required and everything else is optional so let's give it a name of kyle we're gonna give whoops an email of kyle test.com and we'll say age is 27. and we'll just get that user and we will console log the user now if we run npm run dev start just give it a quick second here and we hopefully should see we have that user being printed out there we go we have an id and age a name and email and the role is set to basic now if i save this file again it's going to rerun it and we're going to get an error if i save you'll see we get an error because our email is the same unique constraint failed on the fields email and that's because we're trying to create a brand new user with the name of kyle and that's why at the very top here what i'm going to do is i'm going to await prisma.user.deletemany that's just going to delete all the users that are currently in our database so that way every time we save we start over with an empty database to make sure we don't run into any of these uniqueness problems and that's just going to be purely for me to show you how prisma works obviously you wouldn't do this in a real scenario now you did notice if i click control space here we can actually specify data for like favorite post and user preferences which is kind of interesting because these are actually models that are not directly on the user these are models that the user references but with prisma we can actually do all that nested creation all in one create function so let's say i want to specify some user preferences i can say our user preference is going to equal an object and inside this object we can use the create function and the create function is going to allow us to create a band brand new user preference so we're going to say create here and inside of create i want to say that our email updates is going to be set to true we want to receive email updates now when i click save and we just give it a second you're going to see it created as a user but we didn't actually get any information from that user returned about their preferences you can see we just have you know id email name and so on if we actually want to get their email preferences returned we need to pass another property to our create you can see we have include and select and by going into include here what i can do is i can say you know what i want our preferences our user preferences to be included so i'll say true now when i save that again and rerun you'll see we're of course getting an error delete many invocation it's saying foreign key constraints failed on the field user preference user id key so the reason we're getting that if we go back to our schema here is just the way we defined our user and user preferences we're trying to delete this user but this user is referencing this user preference and it's not allowing us to delete the user preference because of the user if we swapped around where we are storing our foreign keys that should solve the problem for us so let's do that real quick i'm just going to take this move it up to here move this down into here so this is going to reference a user and this is going to reference a user reference reference id just like that and this will say user preference id get that all fixed around and this right here we want these to be optional and down here we're going to make this not optional and then if we just change this to user reference and then get rid of this auto generated stuff that populated we don't actually want any of that auto-generated stuff get rid of that there hopefully that works finally to get rid of this error we just want to make this optional down here and that'll give us a working version there we go so now we're just saying that our user can optionally have a user preference and we need to rerun our migration so let's just come in here we'll say migrate dev and we're going to give it a name of test2 just to get it to run for us essentially so give that a second that should hopefully run for us and the reason we're doing this again is so that we have this so that it'll actually do our deletion so when we delete our user it'll also delete our user preference as well so now we can come into our script ts and if we just npm run dev start it should hopefully delete that user and then now you can see it created a brand new user but most importantly since we included our user preference here you can see our user preference is showing up in our results so by using include we can include essentially different references inside here also instead of using include we can replace this with a select and a select can do a lot of things for example we can say you know what i want to get just the name so now when i run this it's only going to return to me the name property and nothing else or i could say you know what i want to get my user preference so i'll say that user preference is true and it's going to return to me a name as well as all the user preference information or maybe i want to get a little bit specific and instead i want to select only the id of my user preference so now i'm getting just the name and then i'm getting the id of my user preference so you can nest together these selects and includes but it's important to know that you can only do either a select or an include you can't do both at the same time it's only one or the other now in order to actually understand what's going on behind the scenes with prisma we can come up to our prisma client here we can say that our log here we want to log out all of our queries so we can just give it an array and put query into there so now every time it runs a query on our database it's going to log that query out so you can see here we have this massive list of all the queries that are being run we're doing a bunch of select queries for our delete so this is how our delete works right here and then we're doing a create query right here that creates our user preference it creates our user and then it selects our user and our user preference based on our select section right here this is kind of neat if you need to debug things or worry about performance it's nice you can actually log out the queries i'm going to get rid of this because it's obviously polluting all of our logs which is not something that we want now something else we can do is a create many so create many is just like create but you pass in an array of data so instead of our data here we're going to pass it an array of data instead i'm going to come in here i'm going to create a user called kyle i'm going to create a brand new user and we're just going to call them sally and we'll say that they are 32 and it's important to note that inside of a create menu you can't actually use this select clause so we're just going to get rid of that select clause and we're going to change this to users now we click save this create menu is going to create two brand new users and you can see it returned a count of two to say that it created two users now this right there covers creation but what if we wanna do finding or reading of data i'm gonna get rid of this delete menu right here and what we can do now is focus on the actual reading of data so instead of create many i want to say find unique and find unique is interesting and then it allows you to find things based on unique keys inside of your database so if we go over into schema prisma you can see we have a lot of things that are specified as unique such as our email our id up here specified as unique so we can actually use those uniqueness ids to find different pieces of data this is going to return to us one single user because find unique always returns one so instead of a find query we always have the ability to do aware and inside this where you can see we have options for our email our id and then this thing called age name we'll talk about in a little bit so let's say we want to find the user that has the email of kyle at test.com type that in you can see it found that user right here also we can pass in select or include if we want exactly the same as how we did with create so i'm not going to cover that again here now you did notice that if i come in here a second you'll see we have this age name property that's because in our schema we defined a unique key on the age and the name so the way prisma defines this is whenever you define a uniqueness constraint on multiple fields it'll specify them just like this with underscores between the names and then what you need to do is just pass in an object that contains both your age property which in our case is 27 and the name which is kyle and now it's going to find the user that has that unique age and name combination click save you can see it found that user if we had one of these incorrect and we click save you can see it's going to find nothing because no user has this age and name combo now you will notice though in our where clause we can't search for things like just name and that's because that doesn't have a uniqueness constraint on it there's nothing that just says the name must be unique if we want to search for just a user based on name we would need to use one of the other find queries such as find first find first we'll just find the very first thing that matches a query so we could say where the name is sally and now this is going to find the very first user with the name of sally as you can see just like this now find first very similar to find unique but it allows you to do any property for example if we come in here you can see we have all these different properties we can do our where query on now we also have find many we could say find many and it's going to find us many users that match this so if we hit save here real quick it's going to return to us just one user because only one user has that name but you can see we have an array which contains that sally user now the next thing i want to talk about before we start talking about all the different complexities of this where filtering is things about filtering and distinctness so what we can do i'm going to comment this out i'm just going to create two new users real quick so we'll say wait prisma.user.create.many and this many is going to have some data inside of here we're going to have a name of sally age of 12 and let's see here email is sally test one dot com save that so we've created that user let's create another user here just like that we're getting some errors it looks like uh it's because this console log needs to be removed but it did create those users if we save again it should hopefully give us a uniqueness constraint error i believe it did not actually so let's create sally12 there we go so now if we just get rid of this code and bring this code back in we should hopefully now have three salaries being returned let me just bring this up you can see i just rerun that real quick so i have my formatting correct that we haven't sally which age 32 age 13 and age 12. we have three different salaries being returned by our find many here so if we want we can actually modify this query to do things like pagination and distinctness for example i could say you know what i want to get it where the name is distinct so i can say you know what wherever the name is distinct i want to get sally's so now it should only return one single sally because they all have the same name so when i say distinct on name it's only going to get the first sally with a name we could also do distinct on things like name and age and now it's going to get me every sally that has a unique name and age which it returns all of them because the name and age is different for all of them now a little bit more important than distinctness is going to be things for pagination so pagination you can say take and this determines how many you want to return for example we're going to say take two this is going to return to us two users if we scroll down here we get the salary with the age of 13 and the salary with the age of 12. so it's returning to us two users we can also combine this together with something like skip we can say skip one so now we're skipping the first user sally and getting the next two so we're going to save that again real quick and you can see we get the salaries of age 12 and 32 and we skipped that very first sally with the age of 13. we just have the one with 12 and 32. so you can combine together this take and this skip in order to get these different salaries that you want you can also do an order by so we can say for example we want to order here by the age whoops age and let's do that in ascending order so now we're getting only the last two sally's in order by age so it gives us 13 and 32. if we sort it in descending order instead it's going to give us 13 and 12 because those are the youngest two so now we get to the fun part which is all of the different where clauses that we can do right now we've covered the most basic types of where clause we just say the name is equal to sally and another way you could write that is by putting this inside of an object and saying equals sally this right here is going to be the exact same where clause it's going to give us three users and i believe here we can get the count if we want instead so we can just do that by saying user.length down here and that'll just return to us however many users we found for example we found three and that's because three users have the name of sally we could also do a lot of other things we can say hey you know what we want to get where the name is not sally this is the exact same as not equal so we're saying it's not sally there's only one user that does not have the name of sally and that user if we save this again is the user that has the name of kyle right here we can also use in that's going to say we're going to pass it an array and it's going to give us all the users that have a name within that array so all the users that have the name sally or kyle and as you can see that returned all of our users because every user we have has the name sally or kyle we can also do the opposite by saying not in so i want to get all the users that don't have the name sally or kyle and we get an empty array because all of our users have that name now if we want to take this a step further we can specify we want to do a query on age for example we want to do where the age is let's say less than 20. and let's comment out this name query up here and now we're going to go all the users where the age is less than 20 which is just these two sally's we could also say for example where our name is equal to sally and this will allow us to do like a type of and query we say sally right here this is now going to get all the users that have the name sally and have this age less than 20. if i try kyle here you'll see it no longer returns any users because no user it has the name kyle and an h less than 20. if we did greater than though you'll see that now kyle has an age greater than 20 so he shows up we could also do greater than or equal to and less than or equal to four queries as well on numbers now another important query we want to do is a query on contains so contains allows us to check if the text is contained inside of another piece of text so we could say that our email contains the text at test.com this is going to give me every single user that has at test.com inside of their email and all of our users have that well actually not all of them only the first kyle and sally were created if we want and at test1.com we'll get the salary that has that at test1.com at the end of their email and if we want to be even more specific we could use ends with and that's only going to see if this string is at the end so for example here we have at test one at the end or we could say starts with and we could for example say we wanted to start with kyle and now we'll get all the users that email starts with kyle now that covers all of your basic types of queries for wear but you can also combine these with ands ors and knots so we covered already how to do a basic and by just you know saying name right here would be like sally for example and since no user has a name sally and email starts with kyle we get this returned as nothing we could combine this by just saying and like this and then we can give it an array and inside this array we just put all of our different queries so we for example have one query that is going to be our email so i'm going to put that inside of an object just like this we're going to put this name query up inside of here as well now if we save you can see that this is going to work and it's going to return nothing but if we change this to sally for example it will work because it'll return all of our users that have sally at the start of their email and the name of sally now really the only main time you would want to use this is if you want to do a query on like email multiple times so for example we want to come in here with our email property multiple times and we want to check where it starts with sally and where it ends with at test1.com for example and this will return to us just the one sally that has that email we could also do an or query for example we could say where the email starts with sally or we'll say let's say age is greater than 20. that's going to return to us all the sally's and it's also going to return to us the kyle user because their age is greater than 20. finally if we wanted we could do a not query and a not query works very similarly to all the other queries it just negates everything inside of it so let's just come in here we're going to say where the you know email right here does not start with sally click save and now we get just the kyle user because it's the only one that doesn't have an email that starts with kyle or starts at sally sorry and the next thing i want to talk about is how you actually do queries on relationships because you will know that we can do queries here on our relationships for example i could do a query on my user preferences and if i look inside this user preferences you can see we have a lot of the same stuff that we had with our queries before so for example i could say hey where our email updates is true now if i click save console log out all the users where email updates is true we just get an empty rate because currently none of our users have email updates set to true which is fine now if we wanted to do a query on something that's more than just a one-to-one query though we could actually do that we can say let's check all the written post and inside of here we can either do an every a nun or a sum so we can check where every written post has this query none of them have this query or some of them do for example we could say where every written post matches this section so let's say where every written post has a created at that is some you know new date like the current date for example this would be a bad query but it's a good example of what could happen or we could say where the title is equal to test so i want to say is every single post of this pertinent written start with the title of test if so return that user now when i click save and run this it's going to be essentially every user and the reason it returns every user is because none of our users have any post at all so technically all of their posts start with the test of title because none of their posts they don't have any so technically all of them specify this requirement because there are no posts at all we could also come in here with a nun say hey has this user written no posts that have this title and again it returns everything because no one has any post that's perfectly okay and we can do some to say hey do any of their titles start with test and this one returns nothing because currently none of our users have any post so none of them actually have this title to be used now obviously these queries are much more useful when you have all this relationship data going on but this is just showing you what you can do with these queries and also you can do all the fancy stuff you know we could do with starts with here so we could do all the fancy querying that we were doing before and nested as many levels deep as you want to it's going to work just fine so all the different queries we talked about they can be nested infinite levels deep it's just important to know that we have the sum the every and the none that you need to worry about when they're doing posts like this now there's one other type of query that we want to talk about with relationship filtering so let's actually check to get our post here i want to find many post where the user here so our author id actually let's just do author and here we have slightly different information we have is and is not we can say is we can check hey is this a particular author so here i could say is and then we can pass in like age 27. this is going to give me all the posts where the author has an age of 27 pretty straightforward stuff that we can do and this is nice because we can combine it together with an is not as well if we wanted to do like the opposite of an is now that right there covers everything you need to know about reading data so we have all that fancy filtering stuff we have pagination relationship filtering and so on now i want to talk about updating so let's come in here we're going to do this on our user for example and we have two functions we have update and we have update many they both work almost exactly the same it's just that update will only update the first user it finds and update many will update every user it finds that matches the data so update is going to take in two sections we're going to have a data and we're going to have a where so it combines together our find and our create so our data here is just going to be the data that we want to update for example let's change our email from sally1 we'll say like sally at test3.com and we need to also specify our where so what we're going to do is we're going to take our sally so our email where it is sally test.com so i'm taking my user with this email sally at test.com and changing it to sally test3.com now if i save this wait for it to run real quick come down here you can see our user has the name sally and it has that updated email that's being printed out so we correctly updated that user's email and also down here you can see we can pass in an include and a select just like we could do with all of our other queries so again i'm not going to cover that because we cover that in all the other sections now update many is exactly the same as update except it's going to update all the users that match a specific query for example we could say hey everyone that has the name of sally their new name is going to be new sally now if we save this and we wait for it to print in a second you can see it's updated three users and if we just try to find the first user that has the name of sally or new sally sorry so where name new sally click save you can see that we now have a user with that name of new sally so it's updated all of their names to that new name the only important thing to know about update many is it doesn't allow you to do a select or an include so that's really important to know just like with find many you couldn't do that or with create many i mean you also cannot do that with update menu now update does have a few fancy operations when it comes to the age so i'm going to say update here where the name is kyle and i want to update their age so i'm going to say age and i want to increment their age by 1. so we'll say increment by 1. and you will notice we're getting an error here and that's because when you do a single update it must be on a unique field and name is not a unique field so let's do email instead because i know the email field is unique just like that now if we save and give it a second you can see our age for kyle is now 28. save it again our age will be incremented to 29. we can also do decrement to remove one to bring it back down to 28 and we could change this to like remove 10 so now the age is going to be 18 when this resolves we can also do multiply so now the age is going to be 180 and we can also do divide and then the age is going to go back to 18. so we can do these kind of fancy things to our age and just any number in general which is really handy now the last thing i want to talk about is the ability to actually add and connect different relationships to a user by updating it because i could come in here with update and i could say you know user preference and then in here i could specify that i want to create a new user preference and i could say email updates true and that's going to update my user to give them a new user preference with this information but what happens if i already had a user preference that i created so let's actually do that real quick so i can show you what i'm talking about i'm just going to comment this out what i'm going to do is i'm going to say const preference equals await prisma.user i'm going to create a user preference and this user preference is going to have email updates set to true and then we're going to console.log out our preference just like that and it looks like our data has an error with it it says email.true is not assignable to that type i believe it's just an error that actually is not founded let me just make sure oh yeah property user is missing so we do technically need a user is what it's saying like you need to define a user for this but let's just say that we didn't we have this preference and you can see we have an id for it right here i'm going to copy that id and then what we can do is just remove all this code we had comment this back in and instead of creating a brand new user preference i want to link to this one that i just created so instead of doing a crate here i want to do a connect and for the connect what i want to do is i want to search for where the id is equal to that id that we just created so now what i'm doing is i'm taking this user and i'm connecting the user preference that already exists so if we just give this a second you can see it has now connected that user preference with this id and if i just come in here and i actually select this user by saying const user equals wait prisma.user.find first where the data name kyle this should be where there we go i click save oh i make sure i do an include in here i want to include user preference true now we should see it has that user preference which the email updates are true so we can actually connect different things by using this connect to connect already existing objects or what we can do is we can do a disconnect to remove existing objects so instead of connect i could say you know what i want to disconnect the user with this id and since this is a one-to-one relationship we just need to say disconnect true and that's going to automatically disconnect this user now i click save you can see user preference id is set to null and it removed that connection so you can either do a create directly in the update or you can connect and disconnect things that already exist and this ability to do connect and disconnects is actually available in create as well so like if i was doing a create right here instead i could still do a connect i couldn't do a disconnect obviously but i could use a connect right here if i wanted to so you can do connects anytime that you do creation and you can do disconnect anytime you do updates so now what we want to do is talk about the final feature that we have which is the ability to delete and we've already covered half of deleting which is the delete menu function so if we say await whoops await prisma dot user dot delete you can see we have delete and delete many i'm going to cover delete first just so we don't delete our entire database let's just come in here we're going to get that user and we can say console.log our user so for our delete function this works very similar to find we just say where and we can delete something based on a field so we could say like where the name is kyle we'll notice we get an error when we try to do that and that's because delete only deletes one user and it must be on a unique field our email is unique so let's say where the email is kyle test dot com give it a save here and you'll see it prints out the user that it just deleted and now if we save it again you'll notice there's no user to delete so it's giving us an error hey this failed there is no user to be found for this delete and we can do the same thing with delete many let's say i want to delete all the users that have an age that is greater than 20. so now this is going to delete all users with an age greater than 20. i click save and you can see it deleted one user because only one user has an age greater than 20. or if i just want to delete everything i pass it nothing click save and now it's going to delete all the users in our database and that's just two users and that's all you need to learn about prisma now if you want to compare this to one of the most popular database providers in node.js you're going to want to watch my mongos and mongodb videos they're both going to be linked over here i highly recommend checking them out to compare them to prisma with that said thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 377,328
Rating: undefined out of 5
Keywords: webdevsimplified, prisma, prisma js, prisma db, prisma database, prisma orm, prisma javascript, prisma guide, prisma js guide
Id: RebA5J-rlwg
Channel Id: undefined
Length: 59min 25sec (3565 seconds)
Published: Tue Jul 05 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.