Build and Deploy a GraphQL API using NodeJS (tutorial for beginners)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up noj developers welcome back to a new live stream today I have prepared something special for you today we're going to build and deploy a graphql API using only node GS this tutorial is the goal of this tutorial is going to uh help you learn uh graphql fundamentals and the focus of it is going to be on the server how do we build a graphql API ourself because we have a lot of tutorial on this channel uh for focused on the client side where we are consuming a graphql API from rack native or rjs if you are interested in that you can check it out here but today we're going to focus on the server in our previous tutorials the way we have implemented them was using a graphql uh was building a graphql API using IBM staben this way uh IBM staben allows us to easily create and build uh graphel apis from different data sources if you're not familiar with it check out other tutorials we have it's really easy to build it and uh deploy it and it's also very easy to scale um the way it works is in the previous tutorials we simply run a CLI command like steps and import database then stepen uh was doing the the magic and in return we got a fully functional graphql API the thing is that the magic that is happening behind the scenes uh when you know what's happening like you can understand very well the benefits or uh you can understand how to work with it but if uh graph is something new to you I believe it's hard to understand okay what's happening there how is everything uh so so uh easily created so to better understand that we decided to create this tutorial where we will learn and build a doityourself graphql API for that we're going to only use node GS we're going to use the graphql HTTP Library we're going to use mongodb to connect to a database to see how we can pull data from different sources and we're at the end we're going to deploy this to Amazon ec2 to make our API um publicly available so I approach the uh the guys from stepen and they love the idea and they decided to sponsor it so thank you very much for making this tutorial possible and thank you for for being our uh being together with us and making graphql more accessible to developers if you're ready let's get started and let's see what we're going to do [Applause] [Music] today all right so before um our tutorials are very very Hands-On and practical and I can't wait to get started with a coding but I will cover like probably maximum 5 minutes of theory about graphql what it is and because I guess if you're in this tutorial you most probably heard already about graphql and I would try to explain you uh how to work with it and uh by by building something with it so let's start with just a little bit of theory so here it is graphql what's the benefits of graphql first of all it allows us to First descri describe the shape of our data describe how is our data looking um then from a client uh from a client side we can ask for specifically what we want so compared that with a rest API where we send a request for let's say posts and the rest API will give us all the information about posts with graphql the benefit is that we can ask specifically for the fields that we want and in result we get predictable results with only the data that we requested so compare graphql apis with rest API in rest API world uh usually we have a separate endpoint for different models for example SL player/ team/ matches and uh we send a request where the API gives us all the data that it knows about for example a player or a team and then uh the the the worst case is when we need a lot of dat data for a specific screen in that case we would have to send multiple requests to AR rest API just to get the data that we need so uh with graphql on the other hand we can build these queries to get all the data that we need in one single query so from a client side we send one request with information like give me information about player their teams and matches it graphql is going to go ahead and grab information from where it's stored we'll process process it and then we'll give it back to the client so yeah that's small some some of the benefits uh like really really short we're going to see today more of them but uh what makes like the The Core Concepts of a graphql API on the server side uh are the following we have types which we saw in the previous screenshot as our way of describing our data we simply create the types we say What fields it have and what uh what is the type of that field very similar to how typescript is working but don't confuse it with typescript this is a graphql type definition then here on the right we have resolvers resolvers are simple functions that tell graphql how should I go get the data for this specific field so in some cases he's going to read from from database layer in some cases is going to go ahead and call another API or we'll do some processing around it but in general like a resolver the goal of a resolver is to go get the data for a specific field in our types and then we return the response so that's uh everything that I'm going to cover about the Fury at this stage let's go ahead get started set up our graphql API and a lot of things will make more sense as we go so before we do that let me say hello everyone who is joining us live how are you doing guys Muhammed wasama Victor Robert Julio from Denver Colorado hello Julio you already know that what I was about to to ask where are you joining us from let's see the geography of our live stream come on my keyboard of course disconnected uh let me go ahead and uh start by I think sometimes I'm working in a terminal but today I feel like just uh opening up visual studio code and starting from here have a lot of things in Visual Studio code let me go ahead and do close folder yes just to start a blank new Visual Studio code uh you don't need any kind of fancy uh editors you can do everything like even in terminal uh but of course it's going to be easier if we have a visual editor so what I'm going to do here is let's go ahead and do file [Music] uh uh I just realized that I never created like a new project or a new folder from Visual Studio code and I'm not even sure that it's possible we can open it so I think that the first step is going to be to go ahead and create a new folder and that's where either you will going to use um your files or I'm going to open a simply a terminal to do it a bit faster I'm going to go ahead in CD my project let's do projects YouTube and let's do 0.2 19 and in the all we have to do is create a new empty folder in which we're going to create our nodejs server so let's go ahead and create with m m Deer uh the folder called graphql test and let's open the newly created folder with Visual Studio code you don't have to do it like necessarily with terminal a easier way would just be to open the the files and create it that way it's perfectly fine and here after we open that folder in Visual Studio code here we have it we do not have any files yet in that folder so that's why let's go ahead and open a terminal window in our Visual Studio code from where we will start by initializing a new uh nodejs project to do that all we have to do is npm init to initialize the the project and we can even provide with Dash Why to say yes to all the questions that it's going to ask so this process what it happened is it created a package.json file and uh the next step in the package.json is going to be to to create our server file so let's go ahead create a new file in our project called server dogs in This Server doj if we simply do a console log hello what we can do next is we can run and execute this server.js using node and provide the server.js file in the console we should see the hello world okay so uh if you're interested my node version at the recording or this video is 20 hopefully you can see it well this way now I'm going to go ahead and open up the um graphql documentation let's write graphql dog is it going to be here yes I think so and we're going to follow the the documentation but at the same time take some detours so if we go to graphql dog let's go ahead and press uh get started in the code tab let's go ahead and choose JavaScript here from the different uh servers that we can build with I'm going to choose the first one the graphql dogs which is the most simple graphql library to build a graphql API so let's follow this documentation what we have to do is first we need to install the library called graphql to do that I'm going to run npm install graphql in our terminal what this has done is in package.json we should see the dependency of graphql here perfect now if we look at the documentation let's go ahead and write our code in the server.js file uh we're going to first let's go ahead and basically copy paste this code and then I'm going to explain uh what it does and we're going to play with it to see how we can adjust it so from the documentation let's go ahead and paste the code and if we for example now we're going to do node server.js what we should see back is a response which is an object with data and then hello and then hello world string that's the hello world and let's have a look at what do we have here in the hello world example um as I was uh telling you before our graphql is Created from two things from type definition and the type definition we see them here which means that we have a query and the query has Fields hello is the field of our query type and it returns a string this is only half of the equation this is specifying how what is the shape of our uh graphql API what types or what data it returns then we have a root value and this serves as the resolver the resolver is specifying how should we go and get this data it has the hello um it has the hello uh field in order to provide to to specify how should we provide data for this hello and what it does it simply returns a string hello world in more complex situation that's where we're going to for example fetch data for example from database then process it process and then return the data so that logic is going to happen in our resolvers here um and the last step here was us simply executing a graphql uh query so we provided the schema that we created we provided the root value and we provided the source basically what query do we want to run here we specify that we want to get the value hello and then we simply logged it on the console now I in order for you to test uh try yourself to go ahead and add um another query that will return the age as an integer and that age should be a hardcoded value of your age then try to execute this in the graphql query and what the goal of this exercise is when you would execute node server.js you should see here age and here for example 25 try to do it yourself based on the example that you see here and think about what should we change and after you have tried it let's go ahead and try to do it together so um again whenever we are uh working with graphql we are two sides of a coin the first one is the type definition we need to specify that hey there is a new query called age that will return in this case not a string but an integer this is another type that graphql supports by default now I'm going to skip adding the the in the root value here the resolver and I'm going to go ahead and in the run the graphql query I'm going to say besides the hello or instead of hello I want to get back the age if I'm going to go ahead and execute this query what do you think will be a result will it be an error or will it have a value well it's not going to be an error but the value of the age is going to be null because the age is find in our type definition but we didn't specify how should we resolve this value how should we yeah where should we get it from and uh whenever and yeah that's why we see null now if I'm going to go in the root value object and add here after the hello another function called age we can either hardcode it with 25 and this will also work yes H25 uh or we can provide a function that will do some calculation or it will do some fetching and then it will return the value 25 that's also possible and it should be an arrow function here so if I'm going to do that we see that it's also 25 so that's all it takes to build some um end points we specify it in our type definition and then we provide a resolver of how we should get the data so at the base of of graphical apis everything is super simple and fundamental then when we start adding multiple stuff around it validations mutations and so on it might feel that it becomes more uh complex but if you take it step by step as we do as we will do in this tutorial everything will build up on top of each other so it's going to be much easier uh all right so that was we hello world but as you can [Music] imagine should I or shouldn't I to yeah I think I'm going to do all the tutorial in the same um in the same project and for that reason let me go ahead and do a g init to initialize git so that uh later you're going to be able to look through the commits to see to compare it with your code and I'm going to do here a new file get ignore because I want to ignore at least the node [Music] modules now if I'm going to go do G status we see that we are about to commit we're about to add the G ignore the package the package and the server without node modules that's important let me go ahead and do get ad git commit minus M uh hello world graphql at this moment it's not even an API at this moment our server is a script because to interact with it we simply execute it with no JS it runs everything it gives us back the data and then it stops a server on the hand will listen for incoming HTTP requests whenever uh it receives request it will send back the data so let's go ahead and see how we can transform this graphql uh schema and serve it over HTTP as a server to do that we can continue checking the documentation and let's see the next page of running an Express graphql Server Express is a package that allows us to run HTTP uh API I in no GS so let's go ahead and do the install the following libraries the libraries that we are going to need next are let's do npm or let's do clear first uh the libraries are npm install uh Express because the express is the library that will allow us to create this server that will listen to incoming requests and the graphql HTTP which is um tool to create a graphql API um very simple Library very minimal not sure if it's used in production a lot but for the learning purpose it will do its job later on we're going to see and we're going to start using different libraries for our graphql server but for now just to to learn and to understand the fundamentals this should be more than enough so if we look in the package Json we besides graphql we have Express and graphql HTTP let's go ahead in our server and let's start by importing Express from not from um but equal require Express a bit later I'm going to transform this project to a to a module in order to use import from because I don't like the required way of importing but for now let's let's keep it simple and what I want to do uh what I also want to import is I want to import something from the graphql HTTP and what I want to import is the create Handler it's a way to provide a schema and to create a Handler Handler that later we that we can assign to express okay let's go ahead the last query that we are running here using pure graphql we don't need it anymore because now what we want to do is we want to create an uh an application an express application we're going to do that by creating V express application and just to to to do it like really like step by step what I'm going to do now is I'm going to say that our application uh for all the requests that are coming to let's say graphql let's simply return hello world and then we're going to console log a API running on and we're going to do local HTTP Local Host and the yeah we need to do a up. listen to start listening to incoming request and here we need the to provide the port so let's provide Port 4,000 and here in this console log I'm also going to do 4,000 so let's go ahead and uh not even SLG graphql but yeah just simply all the requests that are coming to the slend point should return hello world not even sure that it's going to work but let's try so let's do node server and we see that our API is running on Local Host 4,000 if we open this in browser um yeah probably it's not going to work because we need to return a response uh I wanted to do it step by step but better than that what I'm actually going to do is I'm going to right away create the graphql Handler and the graphql Handler we want to mount it on the/ graphql and the Handler will be created using using the create Handler and here in the options we need to provide two things we need to provide the schema which has the name schema so I will have to do schema is equal to schema and then root value is equal to root value but because they have the same names the key and the value I can simplify it like this so now our our graphql that is being served over HTTP is listening to uh requests on the graphql SLG graphql endpoint so what I'm going to do is I'm going to stop the server run it again or even better but I'm going to show you a bit later and let's go in our browser and if I open Local Host 4,000 we see that we cannot get here but if I'm going to do slash graphql uh uh Slash graphql we are going to get an error right come on why it take so much time did they forget something API listen oh the create Handler should be imported a bit differently so yeah the create Handler I forgot shouldn't be imported directly from graphql HTTP but from the graphql HTTP SL Leb sl/ Express and now I'm going to restart server and in order not to have to restart server always we can add the dash-w here and no just now can automatically restart the server whenever we are doing some changes for example if I'm going to do here hello world one to fre save it automatically restarts the server now if I'm going to go to the Local Host SL graphql we should see the message we should see back like the error with a message missing query but if I'm going to add the question mark query equal hello and I know you cannot see it very well but the answer is Hello World 123 and I'm going to add it here just for you to see what let let's do it like this test and I'm going to do it like this so you can see the test request that I'm sending I'm sending a get request to the graphql and because that's what we uh that's the end point in our express application then we are sending the query directly through the URL parameters and here we are querying the hello field from our query here if for example we want age we can change here age or even do hello comma age and now if we look in our terminal we can go ahead and press on this URL it opens up and our data result has both hello and AG so that means that now we have a fully working graphql API which is running locally and can serve requests whenever we are sending this request here no matter from where from our application if we have access to our Local Host we're going to be able to get the data that's not usually how it happens and there are tools that allows us to interact with our graphql API from a visual interface these tools are great for both backend developers to to test their to test their apis to run queries against their apis and also they serve as a great uh resource for frontend developers to to build first their queries before integrating them in the application so one of these tools is graphical uh and it looks something like this so if you saw this interface this is an open source tool to build and interact with your API called graphical um by when preparing this tutorial I actually found a better solution for a different graphical interface basically different distribution of graphical and it is called Ruru so let's go ahead and install Ruru Ruru npm in our application and and add it in order to for us to have um to have a graphical interface to interact with our API to do that what we have to do is I'm going to stop this server probably and I'm going to run npm install Ruru Ruru Ruru uh then also from the graphql here let's go ahead and import not import I always do import it's not a module yet so let's do require Ruru slash server right and the value that we want is run HTML is it V Ruru HTML not run now we simply have to to use this Ruru in our express application let's copy it from the documentation and let's add it after our graphql here so what we are doing here is whenever we send a get request to the slash end point of our API we are going to handle this through the Ruru HTML and this Ruru is going to connect our SL graphql to send it to our graphql API now if I'm going to go ahead and do noatch server.js and open up Local Host 4,000 now we should see a an actual for you you should see a lot of comments here uh but this is the visual interface with which we can interact with our server what we can do is first of all we see it as a we use it uh in a lot of cases as a documentation of our API and what's possible so if we open the first up here we see the documentation and we see that we have a query here if we press on the query we see that the query has two Fields the hello and the age field so what we can do next is through the Builder through V Explorer we can create a new query for example my query that will will query the age and maybe the hello if I execute this query on the right side we should see the result the data that was returned in a lot of cases I'm not going to do it through the Explorer for checking these boxes I'm going to right away write it here so the minimal query that you have you can run is opening the brackets and now specifying the field from our queries that we want to execute the field is for example age so if I do that that would be data age or the field can be hello in our case we also get autoc completion hello world so this is the minimal query but uh sometimes we can also name this operation and and it's advisable to name them especially from client side uh because with naming them we can also use variables later and so on so to name the operation first of all we need to specify the operation type the operation that we are executing can be either a query which is supposed to get data or a mutation that we're going to learn a bit later that we're going to use to create or update data so by running a by defining it as a query here we can specify the name that we want to give for this query my first query then opening the brackets or not even opening the brackets because we already have opening brackets right I can execute it and it's the the result is the same but now this is a named query uh and later on we're also going to be able to provide here variables age for example data age perfect so uh going forward we're going to use this graphical uh graphical interface to interact with our graphical API as we will build and as we will add new features to it perfect let me go ahead and uh do get ad and get commit perfect let's talk a little bit about a different um where is it let's go here going to close some of the stuff and let's go into the uh getting started guide in the graph Quil clients here here it explained how we can uh interact with our application we are using a version of graphical you can also use Postman or insomnia uh insomnia was really great when I was working with at the previous startup uh I used insomnia because back when Postman didn't support graphical API so insomnia was great but graphical is perfect for a lot of use cases when we're talking about um client side uh libraries in that situation there are a lot of uh choices there you can go with Apollo client to query and fetch a graph qu API you can go with uh relay you can go with like yeah again uh the focus of today's video is not going to be on the graph clients uh so let's go ahead and continue to the next documentation which is about basic types by default graphql support the following scholar types or basic types we saw the string and int and there is also the float Boolean and ID so for example if we have here let's say we have string we have AG in we can have also I don't know weight uh as float and Boolean is is is is uh over 18 let's do here bullan so we can return this from our API and is let's do it like this so our API is supposed to restart automatically so after all the changes we simply have to save a file and go back to our graphical interface here whenever we do some changes to the schema we can press on this icon to refetch the graphql schema because now if I'm going to do here wait it's going to say that there is no operation weight on type query after I press on this icon it's fetching the new schema and now it knows that there is a weight and I can also do a is over 18 if I send that's the values that that it returns so this uh in a short these are the these are the four most common scholar types that we are using in graphql we can create and Define our own scholar types for example a date scholar or something else um but I'm not going to cover that uh at this moment in other cases we uh we will we will create custom objects for example a user would be an object that has like name username password and so on uh that we're going to cover in a moment but before we go uh go to the next step I want to mention that all the colors that we see here they are nullable a nullable value means that we can simply return for example null for the weight and that would be perfectly fine because by default these colors are nullable if we want to make them non nullable uh I'm pretty sure I'm pronouncing it wrong then nullable but go with it if we want to make a field non-nullable we simply have to add the exclamation mark after the the type that we specify so now if I'm going to execute this query we're going to see an error that it cannot return null for a non-nullable field query weight so in this situation we should we must return uh a number so this is just uh to to understand that if there is no exclamation mark that means that that value can be null and if there is an exclamation mark that value uh is required we are calling it non nullable but I think it makes more sense to call it required and optional so no exclamation mark that means optional exclamation mark required so that's very important and that that is also like the the contract where the promise that you are making to let's say the frontend uh developers saying that Hey whenever you're going to send this query no matter what I'm going to return a a float value even if I don't have it I'm going to return something very here so that uh on the front end we can be sure that when querying this weight it's going to be a float and it's not going to be null so we can safely do some operations with that weight that's great because it creates like a contract between the front end and the back end something that you cannot easily do with a rest API all right so that were the basic types and also the uh the nullable and non-nullable both types there is also a way to create lists in graphql we are calling it lists I would call them array arrays for example if we want to create an array of hobbies the Hobbies if we want them to be string for example they should be string all we have to do is well usually you would expect it to be like something like in JavaScript it's an array like this well it's a bit different the only thing is that the string goes inside this brackets so if it goes inside that means that the hobes is an array of strings or a list of strings so let's go ahead and add the resolver for our hobes because without that our array if I'm going to do Hobbies here refresh send our Hobbies array is going to be null let's define hobbies here which is going to be a function that is going to let's say return um I don't know carting and F1 and the simulator these are the the hobbies that we're going to return so if I go back here and I'm going to send the request we see that the Hobbies is indeed an array of uh of strings uh while we are still here like the concept of of lists probably is not that complicated but sometimes uh there might be some confusions around whenever we want to make them required or non-nullable because there are two things that we can make um required here firstly we can make the whole whole obious array required by putting the exclamation mark after the array what that means is that if we forgot for example to define the the resolvers and if we send this request we're going to see cannot return null for non nullable field query Hobbies meaning that the Hobbies no matter what it should return an array it cannot return null but the values inside here here which we Define as string they still can be null so I can still have null here and the API will not complain I can send it we see cting F1 null and then simulator if you want the values inside the array to also be required you add a number exclamation mark after the string so as you can see we have a required array of required strings so now if I'm going to send the same request here we see that we cannot not return null for non-nullable field query Hobbies which means that we cannot have a null value here so that are the two things that we can make required the array itself and the values inside the array okay what's next let's go ahead for the documentation okay the next step is the arguments very important um very important step um in a lot of cases when we execute let's say query where especially when we execute M mutations we want to send some data to the server for example for a query let's say if I want to execute a query hello and also provide there the the name of a user I want to be able to send this name as a variable to our query let's see how we can do that uh let's add it to the hello and yeah I want to say hello let's say hello plus username Vadim but in the hello not world but hello uh and viim so now if I'm going to execute the hello it's going to say hello Vadim but at this moment this Vadim is hardcoded I want to send it from our query like when we execute the query to do that we first need to specify the arguments for a field well in graphql everything is uh in graphql we have types and in this situation the query is a type and we have Fields every field can have arguments no matter how deep or how nasty it is uh and we're going to see that a bit later but that means that the field hello can have arguments to do that we specify them in a similar way how you would Define the arguments of a function we open the brackets and here we specify the the name of that argument let's call it name and then we need to provide the the the the type of the name or the type of this argument so our name should be a string that's the first step um the next step is how do we get this arguments inside our resolver we get that as you can guess through the first parameter here so if I do here ARS I can expect that there will be the ARs do name because that is how we called our argument name so I can return in said hello and the name that was passed through the arguments let's see if our API was restarted successfully it was and let's go to our graphical interface and if now I'm going to send this one here we see Hello undefined why because we didn't send any uh any names there one way would be to make this argument required by specifying that the name should be a string and it should be non-nullable in that case graphql will prevent us from running this query and will return us an error saying that the hello should have a argument name and if I'm going to actually refetch our graph schema uh the graph the the the graphical interface the Ruru is actually saying us with the field hello argument name of typ stream is required but it does not provided so to provide it we see simply open the the brackets we specify the uh the name of our argument and then the value for example Vadim now if I'm going to run it we see Hello Vadim here perfect uh this is a simple way to send arguments but what we have done so far is we actually hardcoded this argument inside our query uh definition when you're going to execute this from your uh client side from your application you're going to copy this query and we are going to Define it there by having it hardcoded here first of all the query becomes not reusable because if we want the user to type his name and then to to send the query we're not going to be able to reuse it so what we should do in stand is we should use uh variables query variables to define a query variable on our query itself let's go ahead and Define it we were we will Define the variable with the dollar sign so let's call it dollar sign name and we need to specify what type it should be the name should match exactly the type of our uh variable that we want to use should be should be a required string let's say string required now we take this dollar sign name and we send it to the argument name of our hello field now if I'm going to execute it we're going to see that the name was required but was not provided yeah because we just defined it but we never specify what the value should be of this name we can specify variables by opening the variable tab here at the bottom and providing a JavaScript object with all the variables that we need here for example name and we're going to provide the name Vadim if I execute it now we see that the name from here I mean Vadim yeah the name from the variables object was sent to our query here and from our query it was sent to our hello field and from our hello field it was sent to our resolver resolver through arcs and it was used in the resolver for for something like later we're going to use it to to fetch data for example you can send ID like this and so on and in a lot of cases we simplify this by destructuring it right away so instead of taking arcs do name we can destructure the field name right away here and it simplifies it because we see that the hello has a name here hello is using the name here and it's going to work as it was working before Alex Hello Alex and that's everything about uh arguments and variables in graphql let's go ahead and do a get add get commit uh query arguments or just arguments perfect any question so far guys if not let's continue The Next Step what would be the next step so we learned about this object types okay okay okay when we have all right so let's talk about the object types I'm going to start with a very simple and basic object type and then we're going to slowly move away from uh to to different way of defining our schema but at the core um we we learned about the scholar the default scholar graph qu types which are string integer float and Boolean in a lot of cases uh your objects will be much more complex so you have to Define your own object type for example you have users with v Fields you have posts with their fields you have comments and so on so ADV the core object type is a custom type that we Define that is built of other scholar types or even other object types to do that we Define them in a similar way how we Define the type query well I think is the query is a default type uh but the rest that we're going to Define is going to be created by us for example we can define a type here user and we can specify that the user type will have a next field ID of type integer and let's say uh name of type string having the user type here we can define a query called user that will return the user type like this so now what we have to do is we have to define the resolver for our user query let's go ahead in our root values here and we can say user is going to be a resolver that will return the following object the graphql types type object Maps directly to a JavaScript object so we simply have to return an object where we have ID and name so let's return here an object with ID one and name let's say v a lot of things are hardcoded but that's for with a purpose like to keep it simple let's go in our graphical interface let's refresh here and instead of quering the hello query let's go ahead and query the user and now if you look before we simply query the hello if we query the user which is not a scolar typ type we're not going to need even the name here the graphql doesn't allow us to query user because user it automatically uh refreshed it for us because user is of a type of vaness color so it's a it's a custom object type so we need to specify What fields from the user we want to get back for example if I specify V only viid here and run the query we're going to see that we give get back the user with id1 we can optionally also add the name of the user and here we're going to have a name V the same thing for example for a post you can define a post here type post ID integer but I'm not going to over complicate this right now yeah okay so this was our custom type that we defined we have a type with their fields and the fields have their own type um again uh the the fields inside a custom type we saw that they are scholar here integer string but they can also be uh mentioning other types for example a user can have posts of an array of posts a user can have friends which is an array of of other users a user can have I don't know invited by which is just a user so as you can see by specifying types and the relationship between the types we create this graph that the from where we um we create the graph of data and all the connections between this data in a simple and uh easy way and then the front end for example can can create very complex queries to get the data that they need um the problem is that these connections like to post to to friends and user a connection between types I was not able to uh to create them by default with this uh with this approach where we have a schema and the root value because root value is providing all of these data to the queries what I need is I want to provide custom resolvers to some of the fields for example in the user I want to have here a post that will return an array of posts but this post should have a custom resolver to tell how should we get the array of posts knowing a user so to provide custom resolvers in this situation what we can do is we can create the schema a little bit differently um instead of build schema from graphql I I'm going to what I'm going to do what I'm going to do let me go ahead and comment out our existing schema here and let's go ahead and start creating the schema using the graphql schema imported from graphql it should be an object so we created using the graphql instead of a build schema this is a class so we are initializing it with new everything starts with a schema and the schema should have uh the queries which uh is going to be a if we look in our schema that we had before our query is a type is an object type right so the query will be a new graphql object type also imported from graphql so the object type here will have two things the name the name of object so the name of the object is going to be this one this is the name that we had before the query type and it's going to have a list of fields so a type has the name and a a list of fields the fields we can start looking into this query well there is the let's say hello and I'm going to start with a simple hello world the hello is uh uh a string the hello field should return a string right so let's simply say that hello is an object where we have have a type graphql string another object imported another class imported from graphql to specify that the hello is of type string and here is where we can provide directly the resolver so the resolver is the function that previously we Define in a separate place but now we can Define them together hello world so just like this we have a schema with queries with one query called hello that returns a string we don't need the root value anymore so I'm going to comment this out and in the create Handler the only thing is that I have to remove root value and only leave a schema the graph it allows us to add resolvers even to custom types for example example um I wanted to show you this in order to show you how we can create like custom resolvers to connect like a user and a post but to be honest I don't even want to continue because this way of creating is first of all very verbose a lot of code a lot of configuration uh very easy to get confused and also same could be accomplished here you don't have to to uh to follow along but just have a look and then we're going to see a better approach for example if I want to have uh a query to get users right let's focus on getting users for which we have we need a custom user type to do that in our schema besides the query we are also besides the query which starts here and ends here we going to have another type called user or let's even uh create it separately for example we can do that by creating the user here using new graphql object type the object type has a name and the name we're going to call it user and it has a list of fields it has fields which is an object the user has two Fields ID and name so let's do ID ID our ID is of uh is an object where we have type and the type is graphql graphql int is there a graphql int probably and the resolver well yeah in this case I don't need a resolver and I'm going to explain in a moment why I don't need a resolver and the second field that our user has is a name and the name has a type of graphql graphql string so now that we Define this object type here we can go ahead in the query add in the fields of a query add another query as you can see like it's very hard to map even for me that I have a bit of experience with graphql it's very hard to map like where should we add things but uh in the query Fields after hello so we need to see where hello is ending it's ending here we need to add a new query called user this query the type the return type of user again I'm going to reference back our easiest type definition at the top that we're not using anymore the user query will have a return type of user type we created this user type here so let's specify that the type will be user and we need to provide the resolver how to resolve it so the resolver is going to be very similar to how I had it before basically return ID one and and then the name so just like van if I didn't make any mistakes any typos uh our server should be restarted and I can go back I can restart and besides hello I can also query the user and the user will have an ID and will have a name so if everything is working it should return ID one and name V uh that's good uh but again it's very it it has a lot of boiler plate anyway we're doing this just to to learn the fundamentals shortly I'm going to show you a better way using a simple Library how we can do that much better uh the think the think what a graphical object type of this structure will allow us to do is provide custom resolvers first of all you might think why we didn't provide a resolver for ID and the name well we can for example in the name if I provide here a resolve value uh that will return overridden name is that how you write overridden probably not but you'll get the point if I'm going to send this request again we see that ID Remains the Same but the name is overridden so the name is not the name that we get from the User resolver it's the name that we get from the resolver of the name field why it was working before without a resolver graphql is uh smart enough to say that hey if there is no resolver we simply will take the value with a field name from the parent so from the whole user object that is this one we're going to check the name and we're going to resolve to that one so if we don't need to do any changes to that value we can have it here we we we can leave an empty resolver and graphql will simply take that value and will return it there but in graphql we can provide resolvers for every single field no matter how deep and nasty they are so that's where a custom resolver can be handy for example what we might do in some situation is let's say we want all the names to be with capital cases like instead of this I want to make sure to trim the string and also to make it capital like if the database will return or something like that I want to from the user type to always stream and uh capitalize the the string that we want to return we can do that here in the resolve but first of all how do we get access to the name we get access to the name through the first parameter of the resolve here which is the called OBG the object is basically object representing our parent uh our parent object so if I simply will say OBG dot again if I have return over read the name it returns over read the name if I will do OBG Dot and the field from the parent component that we want to return is called name if I do that and run it again we see that the field is returned as it was returned from the user resolver but we want to for example trim that string to remove all the white spaces from back and front that's a very common way to provide a very simple resolver for a for a field and make sure that always when we query the name of a user it's going to be trick no matter where it's taken from it's going to be trim and also you can do for example to to lower case is there such method yes and if I will do to uppercase is going to be all capitalized so just like that we saw how we can provide a custom resolver and we understand how we can access the parent fields from the resolver so here we are working in the resolver of a field called name and the object represents the parent and to demonstrate that I can do a console log OBG this if we're going to look here when sending this request we're going to see that the value that it gets is the value of the previous resolver that was executed and the pre resolver that was executed is this one of a user so sometimes it might even have extra things that might not be in the type definition but for example in the database ver hey and with these extra things if I send the request I might not need them to necessarily return to the user but I need them to do some operations for example I might have the is ad admin uh is admin equal true so if for example from database when getting a user I'm going to have a EAS admin through I can access it through the object resolver over a name and I will I can say um const let's do some some interesting use cases here let's say if OBG do is admin the name will always contain admin word so I will say return return name not name like this but OB not yeah the name variable and then admin otherwise I'm going to Simply return name so you're going to see that even though our schema uh our schema that that we can look at the documentation here for the user it never mention like is admin or not it only has ID and name we used like some data some properties from our previous resolvers to adjust how we return the name so now we see that V admin just because the previous resolver has this is admin true if it would be false and I would send it again I will see only the name because that's the logic that we added so that's a little bit of how resolvers are working and how they are executed one after another so when whenever we send a query graphql will start from the topmost uh from the topmost query so first of all it will look at the hello and it will look for a result resolver for this hello field it will check our schema and in the fields it see that the hello has this resolver it will return hello world hello world and because it doesn't have any uh sub Fields it will stop here it will go to the next one the next one is a user well let's go ahead and look for a resolver for this user field and in our schema the user has this resolver let's execute it and then for every single field inside the user let's find the resolver for that specific one for the ID it will take this object and it will go to our object user type look at the ID and look for the resolver it doesn't have a resolver so it simply will return the field from the parent resolver that has the same name so it will simply return one in this case okay it resolved like it got the value ID it doesn't has it doesn't have any uh sub field it will stop here that means that it's a edge field it will go to the next one name it will go again in the user object it will look at the name field and we'll check if it has a resolver yes it has it will call this function resolver by sending to the object the previous object that we saw before so in this object we're going to have access to all of this data and we can do some logic with it in our case we saw how we can process some strings uh sometimes maybe you can add like um a very common use cases to add uh if you're displaying a price the price can be an integer or a float in your database but when you return it to to the customer you can automatically transform it to a string and also display the currency Veer uh another very common um use case for custom resolvers for a user is when for example we have the user maybe that one I'm going to show you later when we have relationship between custom types for example relationship between user and post when a user can have multiple post a post belongs to one user in that case we need a custom resolver to tell okay knowing the user ID how should I go and get information about that user but we're going to see that a bit later because I'm really tired of seeing this syntax of graphql objects graphql strings and so on um I much more prefer the previous way of having a schema as a string because it's very clear What fields a user have if I look here it's clear the user has ID int name String and when creating a query on the front end I can literally come copy it from here and paste it in my query and just remove the the types that's all it takes with the other one if I look at this object if I look at this object it's not very clear What fields it have yes I should focus Fields okay it has ID has name but when it gets complicated when it gets long it becomes very hard to to manage so for that reason in The Next Step uh we we are going to use uh a light library to to Define and create this graphql API but before we do that let's go ahead and do a commit and this was uh let's say graph ql schema ktan thank you very much Krishna thank you Dan Andrea hello Tech code how are you uh in your the question is in your react native course is uh Redux included no we do not uh teach Redux in our qu we are teaching Apollo client because that's a much better way to query a graph API and also Apollo client serves as a global it has a caching mechanism so whenever whenever you're working with mostly remote data besides the the the fetching library that also has like caching possibilities you do not really need extra Global statement management so that's why and if anyone is interested in learning and becoming a react native developer check out academy. noes. DAV where you can learn how to build full Stack mobile applications with rack native Expo and AWS it contains Hands-On projects uh one of them is super big like um you you you basically would build like a full Instagram clone both on front end and back end with a scalable AWS architecture so yeah we have more than 700 students and uh yeah it's it's very powerful and will help you master these Technologies so check it out should be in the description below and we are actually ready to move to the next step there is also like from the fundamentals the mutations and input types but we're going to get there once we are we get rid of the graphql schemas and so on so the library that I'm going to use if we go to the graphql let's go ahead and check code and and let's sort JavaScript by popularity and after graphql here after a polo server we see graphql yoga this is the first time I was trying graph yoga and actually it was very lightweight and very performant and very easy to set up a graph API with this uh Library so let's go ahead and follow their instruction to set it up and the graphql Yoda is going to replace our uh uh graphql HTTP so instead of graphql HTTP which is really basic we're going to use this much more powerful library that is also suitable for production applications so what we have to do is uh add graphql Yoda or install graphql Yoda in our application so let's do clear and let's do npm install graph l/ yoga and with graph Yoda yoga not Yoda not Yoda with graph yoga we can we have this uh split of of type definitions where we write them as graphql strings and our resolvers so we can get back to our uh type definitions and it's going to be much better so I would say let's go ahead and I think the best way is going to be to clean up a bit our code so let's delete some of the stuff just for us not to get confused and we're going to recreate something as we need hopefully we're not going to get re uh let's do that we will still need the express application uh volum think is here we're going to have to replace this graphql with yoga we're going to leave our Ruru graphql interface and we're going to start the server here as it was working before now I'm going to also um fix a little bit our Imports and maybe it's actually time to as we have a clear application to switch to a module to be able to use import statements for that let's open package.json and simply add here type module uh module uh type will allow us to instead of using require to use our traditional import EXP Express from Express and the same here import [Music] Ruru from Ruru and just like that if I open it up and see the server is restarted it's also it's working uh if I'm going to refresh here our H probably it's not going to work because we do not have a graphql end point yet yes that's true so let's go ahead and check the documentation of yoga and I'm going to copy these two things so we have to import create schema and create yoga from graph yoga we create the yoga then we provide the schema definition here a schema has two things it has Type definitions and it has resolvers and and because I it has this comment here graphql it adds highlighting because if we don't have this one it looks like a normal string and in some cases yeah like highlighting is much better because it's more clear like what are our types fields and so one but I'm pretty sure that this is coming from some of my extensions so if you don't see it make sure to have graphql syntax highlighting and I don't have it so I'm not sure if maybe it's built in in thiss code maybe I have this one yes graphql language feature support yeah most probably it's from here if I check the enabled graph ql that's the two things that they have the language feature support and the syntax highlight and and this allows me but to to highlight my graphql type definition by simply adding the graphql comment here so now that we have yoga all we have to do is we have to uncomment this the up/ graphql and instead of create Handler here send there the yoga application so that's how how it looks and if I go go to our graphical graphical interface and refresh it here we're no longer going to have a user but we're going to have a Hello and if I'm going to run it we see hello from yoga that's it that's it that's uh our simplest uh yoga setup but it's again is going to allow us to have like type definitions and separate resolvers so before we move forward let's go ahead and set up a little little bit of our project structure because going forward we're going to learn how to interact with uh mongodb with a database we're going to have a very realistic use case and we're going to try to build it uh as close to a a production ready API as possible still keeping some of the things um uh simple and accessible for everyone so for that reason let's go ahead and uh Define a new folder where we're going to keep all the source code uh it's going to be much more manage manageable if we separate some of the concerns not to have all the source code in the same uh file so in the source we're going to have uh first of all we are going to have a folder called graphql and in the graphql let's create the index. GS and uh graphql index. GS not even sure what we're going to have there but maybe in the index. Gs of graphql let's go ahead and move our yoga Veer or no or maybe the schema yes let's move the schema here so in the index let's go ahead and do for const schema or let's call it schema equal to create schema from graphql yog yoga and here we're going to basically let's copy it from here create schema let's go in our graphql and call it like this now let's simply uh export let's export con schema from here export so now we separated our let's say schema from the rest of our boiler plate just to make our server work so what we have to do is we are going to in our server.js let's import uh schema from Source graphql index now I'm going to provided here in the create yoga and I'm going to clean this up a bit okay okay okay now back in our index here what we can also do we can separate the type definitions from the resolvers um where not to to to over complicate this we're going to do that as our file gets bigger but first of all let's have a look if everything is still working so I'm going to check if our API is running probably there is an error here failed running server because cannot find module what which module it cannot find schema is it because of import schema there yep so if I do import schema from Source cql index export cost did you mean to import oh index.js it wants index.js that's definitely possible to be adjusted for for settings not to have to specify the extension index.js uh because it should even work like this it should automatically take it but anyway it wants index CH I'm going to give it and we're going to continue and this schema will be postive create yoga okay now it works if I go here can refresh and I can still run the hello okay that's good uh let's see how we can add the same configuration that we had previously about the user so to do that uh in this situation we have to do two things we have to define the type the qu the type user the query that will give us an user and the resolver for uh for the query so starting with let's say defining the type user which has ID of type int and name of type string right uh now in the query we want to create a new query that will give us a user back maybe later it's going to be give us user by ID but now to simplify it when running a query user we want to get back a user object for that we need to provide uh in the query here the user uh resolver for our query the user resolver will return an object with ID one and name VM just with that I can go back here I can refresh and I can start quering our user with its ID and with its name if I run it we have it here so you saw how much easier it was right now to define a new type uh a new query and the resolver for that query compared to how we how much more complicated and more boilerplate we used whenever yeah whenever we use the the graphql HTTP Library so as you can see now it's much uh simpler like this uh and if we want to for example um capitalize the name uh we we remember that we have to create a custom resolver on the user type and the field name for that below the query because the query is the first type which is the default So Below the query I'm going going to Define an resolver for our user and the resolver for our user type will will specify no the the user will have Fields so one of the fields will be name and the name again will have a OBG object from I hope that everything is good with our stream you know H I see no data okay now it's back to excellent connection not sure what's going on today but anyway again how much easier it was to do it here um than we had it before uh what I want to probably try to do right now is to split uh type definition for different things for example I want to split the queries uh about users and so on into a separate file let's see how easy it is going to be and I hope I'm not going to confuse you too much at this moment but the thing is that as we will write more time and more queries here more resolvers it's going to be is going to get uh this file is going to bet too bad is going to get really huge so for that reason let's look at how we can split it using uh graphql yoga split schema it's not stretch but Stitch so combining local remote schemas no let me check the documentation to to make sure that if there is a specific way to do it in yoga Maybe some of examples Express Express should probably be very simple yeah build application type definitions resolve yeah let's check their website because most probably this is not the responsibility of yoga and we should simply merge together two objects um but yeah let me double check that here graphql features schema yeah the the thing is that uh yoga doesn't care about schema as long as you give it a schema it's going to to work but the other guides and solutions here from The Guild so let me let me see and let me think resolvers yeah it's going to be merging the resolvers and for the type depths is going to be providing them like this so let's try by by splitting the the type divs I'm not sure this is for a PO this is actually for something else but let's see if it's going to be the same here so type devs uh can I do here for example let's do here uh queries and let's move everything from type devs to equal here now if I'm going to Simply provide queries here it's supposed to work because we simply took it out uh of there so now if I run everything is working but if I I'm going to separate the type deps into two things the queries type deps and the user type def uh and if I'm going to copy it from here and in the oh come on and now from the queries if I'm going to remove a type user and if from the user type def I'm going to remove a query will I be able to pass to the type devs an array of things like queries and then user type deps let's see it's restarted so if I will execute it's still works which means that it's good because if the type if I would have here a different name we would see that it's an error so it makes it gives me an understanding that it's um splitting the type definition into different objects and providing them to our schema as an array works great but sometimes in the user type definition I also want to keep all the queries related to the user so if I'm going to do here type query and save it there is a query user and I'm going to remove it from the first one it's not going to work because it's we are in a way we have two type queries and there would be a clash and I would expect it's not going to work but actually it does what okay I think that yoga is that smart to do because I was expecting the this to work like this extend type query I remember that's how it was working so I think yoga is smart enough that if it has if it sees that we are we provide in two different parts the the same type for example type query it's simply going to merge them together it's going to extend in other cases you have to Simply say extend type query by providing additional fields in the query so now we keep all that type definitions about the user here and the rest in the queries uh that's good so that would mean that we can in the graphql we can create a new folder called models maybe and we can have here a file called user.js in the user.js I can extract the type definition of our user and let's export how would I call it import type type def yeah yeah I think to to keep it simple I'm going to export it with a name type def so let's export const type def from this file and now in our index we simply need to import it to import it let's import it as following import type come on type def from models then user.js now I can take this type Dev and provide it to the array of type definitions everything is still working let's double check that yes it's still working uh and usually we would have to rename it uh just because uh we're going to have a lot of type depths from the user from the post comments and so on so let's rename it to user now we successfully have split the type definition uh of a specific model of a user for example including his type and his queries into a separate file imported it here where we create the query that's good uh now the next step is to extract and Export the resolvers resolvers in our case is an uh is an object so uh let's go ahead and extract them here for example const resolvers equal and I'm going to copy the whole object resolvers like this just taking it step by step and this way if something fails I know at what step it failed now it failed why because resolvers resolvers create schema oh because I have a comma here and now it works send perfect so tip of the day take it step by step and test all the way now from this General resolvers from index file I want to extract resolvers related to the user specifically this this one from the query and this one for the user to do that I will have a separate const uh user result verse equal to a new one this one first of all is going to have this object about user that's clear but it will also have the query user so it's also going to have query and the user query user like this so now these are user resolvers these are General General resolvers and what we should do is basically we should merge them together to do that we can simply import the marriage function from low Dash because we need a deep marriage we need basically uh if a shallow marriage we'll basically take the user and put it here and maybe we'll take the whole query and replace it here but what we want is we want inside the query to take the field put it here so it's basically we need a full merge between two objects to do that we can take advantage of low Dash Library so let's go ahead and install it uh quickly by doing clear import uh npm install low Dash and then let's import the merge here import merge from low Dash now what we want to do is in our schema we want to merge what do we want to merge first of all resolvers the default ones and then user resolvers and now everything is working the server is restarted no because merge import mer from low Dash what should work come on low Dash is a common just model which not supported exports as name export for okay uh I'm going to import low Dash as underscore and I'm going to use here underscore do merge okay perfect so now if I go back to our interface everything is still working uh but the cool thing is that we have separated the resolvers our general resolvers from our user resolvers and now I can take them from here and move them to our user model and our user model will simply export and I'm not going to call them user resolvers I'm going to call resolvers and when importing it in our index let let's go ahead and import them from user as resolvers and rename it to user resolvers and just like that we have a very general file for our schema that is supposed to Simply put together our schema we can have here for example very general types like type genre of movie and so one or Union or things that needs to be in every places of our uh API but when talking about like specifics for example the type definition and the resolver software user we're going to Simply go here and at the top we have a type definition we know that a user has ID and name and we can query a user and we see the resolvers how we can do that so just just like that is going to be much cleaner and easier to scale it as we will add different um different uh models in our application so let's go ahead now and go ahead and do get status let's do get ad get commit uh we're going to do graphql yoga perfect and the next step is going to be to probably already start thinking about a real use case and interacting with a database but before that I need just a minute uh and I'm going to be back and if you have any questions feel free to ask [Music] them sh e [Music] all right so I am back and yes let's continue the the tutorial and actually before going ahead and starting like integrating this uh graphical API with database um I want to cover other the the other important type of operations that we can run in graphql so far we saw uh how to run a query a query is a operation when we have to get some data from the from the API usually a should never uh create side effects we should never update things or uh insert things when we are running a query for that we have a separate uh default uh type of operations in our in graphql called a mutation and a mutation is there to help us create uh things update things delete things basically operations that have side effects to Define it uh we Define it also as a separate type so let's go ahead in our user actually yes let's go in our user and the same way as we have a type query there is another one that is uh the default is type mutation in the type mutation we can specify as many mutations as we like the first one can be create user and a create user will return back a user I'm going to start simple and slowly I'm going to add more things there now that we have a mutation create user in our resolvers we need to provide their resolver for that mutation well after the query where we see the closing let's go ahead and do here mutation the mutation Has a Field called create user so let's provide here and the field create user I think it's also going to have the object as the first parameter but we're going to check in a moment so let's do uh console log here creating a user it should be Arrow function and it should have a comma here we are not returning anything but that's okay because the user is a nullable field let's just try to ex execute this function and see a console log in our uh terminal I'm going to go back here and if I'm going to try here I'm going to refresh it first if I'm going to try here to call the create user it's not going to allow me because our operation has the type query I would have to first change it to a mutation and only then we're going to be able to access the create user mutation create user of type user needs a selection set for example ID and name because we specified in our type definition in our type definition that create user will return a user back so if I execute it it's going to be null but in the console log we see creating a user that's already good we that means that we are correctly executing this mutation if you see the create user if not double check the the names and where you create this mutation resolver now if I'm going to do here console log object actually I don't need it but just curious what it is if I'm going to run it we see that it's undefined because the uh the because object is basically the previous the the response of a previous resolver that is executed and a mutation is the initial resolver that we are executing that's why the there is no previous M there is no previous resolver uh being called create user is the first one now when we create a user we most probably would want to specify the name so we would need an an argument we will need some input here so let's provide here the input and we're going to provide it we know already from the previous uh steps how we can provide arguments here create user will have a name of type string and it should be required this argument we're going to receive in our uh resolver as the second argument after the object so this is going to be our args if I'm going to do go ahead and console log ARS let's go ahead head and try to execute this one but first refetch our query first of all we see that create user has a required property called name so let's give here a name I can hardcode it to viim and if I execute it's still null but when we look into the console logs that we are doing here we should see that the object is undefined but the arguments has this name viim perfect so the last step is of course uh as I uh showed before would be to provide here a variable to our mutation called name type string and it should also be required and this name would go here and through the variables we're going to provide the name V if I do it like this yes we have access to it so usually in this situation we don't actually need the object ver um AR argument so usually you would see in some some cases this one being replaced with simply underscore because meaning that hey it's the first argument but we don't need it here we only need the arguments and from the arguments we can destructure right a w a name so we can say creating a user with a name but what I actually can do is I can return insert into database and then return ID for example one and name that was sent there so we're not inserting now but later imagine that here You' insert it and then you'd return the the the result now if I'm going to create this one we see that the create user after executing this mutation it added it basically to the database hopefully uh and it's going to do later and it return us back the ID and the name that we sent here and as you can see this name is capitalized it's not the name that we provided here and even if I will add a lot of spaces here I didn't trim it actually but I can do it through the user name dot trim so as you can see even though in our mutation in our create user mutation we never said that this name that is received here and I can show you in the console log what is the actual [Music] name if I execute it if I look in the console log the name is with with lowercase um characters and it has some spaces and beginning at the end uh we never told here in the return statement that this name should be lowercase or capitalized but here it is just because even when returning like the the object from a mutation graphql will go ahead and call all the resolvers for that Fields so it knows that the mutation create user will return a user so it will go take the result that it gets from here pass it to the ID resolver it doesn't have an ID resolver so it's just simply going to take V ID go ahead and pass it to the name resolver because it has a name resolver here is going to apply it so this way it's really helpful to only write things once and be sure that they are always uh executed and made the way you define them like the that's very true like with specific fields that you're applying some changes or with relationships you simply Define the relationship between a post and a user once and whenever we need and whenever we return a user or a post we can automatically query the relationship as well but the point here was about a mutation and at the core I mean from the technical perspective a mutation is very similar to a query it has the same syntax it has the same arguments it has the same return return statement it also has the same resolvers basically from technical perspective everything is the same the only difference is that uh a mutation uh is used with a operation type mutation and it's used with a purpose of updating deleting stuff that's the only difference technically everything behind the scenes is the same when talking about a mutation um we should also understand that it's not the the the arguments are are not always going to be uh Scholars what if our user has also for example age here of type integer when creating a user I want to also send age well we can do that here as comma age in and what I'm going to do in the resolver besides taking the name I'm also going to take the age and here I'm going to return age right so now if I'm going to go here I can also specify the age of a user uh which let's define properly with a variable at the top age of type int forgot the this one and it should be required right or no age and field create user I need to refresh and in the variables let's also provide age here I don't know 18 if I'm going to send it doesn't show me because I didn't select that field in the uh in the result so let's select it to also return the age we see 18 but as you can imagine the the more arguments and Fields about the user we're going to have more of these variables we're going to have here it would be better if we can structure it into a custom type for example the same way as we have a user here it would be nice to have here let's say user of type user right and be able to take the user directly from the arguments and then providing the ID and the rest of the user here here right well this is not going to work because a type cannot be a input what we should do similar to how we have a type we can define an input input uh new user we can even do new user input and this will have the following Fields name and age in a lot of cases the ID is automatically generated so it's not included in the input so now having the input we can say that create user mutation only needs one parameter and that's a user of type new user input and we can also specify what it's required here name and age also required and just like that we can come back here and we see that let's refresh the create user no longer needs a name and an age but it needs a value called user let's define it as a user variable and let's create it here user of type new user input it automatically Autos suggested for us and here it says that the name does not appear in our graphql yeah because we need a user here and the user should be an object where we have a name this one and the age so if I'm going to make it a little bit smaller like this now if I execute it yes it works it has v ID it has a proper name from here sorry and it has the age also from here and this is a easier way like we basically group together all the input in one single uh field similar to how we group together a type specifying the user and yeah later on like most probably in your front end you're also going to keep them like this where you're going to create them when you want to execute the query send them to send them here and it's a much easier query definition much cleaner so that's where we have input type very similar to a normal type but it's used for inputs as arguments hello hello what database do you plan to use uh I'm planning to use mongodb and that's probably going to be the next step are you going to cover all the crude operations uh let's try let's try to cover all the crude operations at least for one model all right so uh that was our mutations and inputs let's go ahead and do git add git commit mutations and inputs okay so let's go ahead and move on to the database integration um even though graphql doesn't require any kind of specific databases to be used because at the core of graphql we have type definitions and resolvers and our resolvers are simple JavaScript functions so we can do anything in these JavaScript functions that you can do in an ogs you can connect uh to maybe local databases to SQL light uh to to remote SQL databases to to nosql databases basically you can do anything that you can do in nodejs for the sake of this tutorial I'm going to use mongodb just because I don't know it's easy uh it goes well together with with graphql it's very easy to to host it with Atlas so yeah let's go ahead and do that mongodb is a nosql database that's very scalable and it works based on the documents we the benefit is that we don't have to specify any kind of um schema we can adjust the schema as we evolve our application so I believe that for this tutorial where we don't have a very clear plan is going to help us uh manage this data the way we need the goal going forward is going to be to create um an API for let's say a social media application having users having posts maybe having comments where users can create comments under specific post posts uh so let's try to to do that and we're going to try to cover the crude operation for at least one of these models and also very important the relationship between them because I really want to query a list of posts with the first let's say three comments and for every comment to also query details about the user that posted that comment so all of this we're going to see how we can do together with a uh with a mongodb database so let's start by going to mongod be.com and let's go ahead and sign in I'm already signed in or no I'm going to go ahead and sign in with my Google and and on the homepage uh on the homepage uh most probably you're going to be asked to create uh organization I already have an organization it's nothing complicated just follow give it a name and after you create an organization inside that go ahead and let's create a new project I'm going to press new project and I'm going to give it a name uh for the project let's say social media let's click next uh give member access okay create project and here is our project the database is not yet deployed for that we need to create a deployment so let's let's press on this create button under the deployment and here we can choose a free deployment uh which basically is going to be free and enough for testing and learning everything I'm going to you can use cluster zero in my case it's uh I cannot use that cluster zero so I'm going to rename it to Cluster one and let's press create deployment at the bottom perfect now uh the mongodb atlas uh mongodb Atlas is a way to create and host our database in the cloud really really easily you can also host a mongodb database uh yourself on any uh VPC on any uh Cloud computer or even locally um if you if you install the mongodb server but with Atlas we don't have to worry about that we host it and we create everything in uh the cloud so the first step that Atlas has done after creating our cluster is it added my IP to the white list to allow me to connect to the database and it also the next step is going to be to create a database user I can call it by and let's create press create database user now that my IP and uh is WID listed and also a database user is created we can move to the next step to choose how we want to connect to this mongodb cluster uh to connect I'm going to select drivers and here let's select no GS uh version 5.5 or later uh and the first step it tells is that hey first of all install the mongodb uh package the mongodb driver let's go ahead and do that in our project I'm going to close everything I'm going to open a terminal and let's start by installing the mongodb driver npm install Mong Longo DB okay after that is done uh the first step is going to be to get our uh connection string here it shows our connection string but I'm going to select this view full code sample to show me how I can connect to our database let's go ahead and copy this code and in our project in the source let's create a new folder called uh and in the let's create the index. GS here in saris index J let's paste the code that we copied and what we see here is some code that we're going to analyze in a moment but first let's try to execute this code to do that I'm going to run node and then provide the source and then index. GS if I execute this one what do we see we see that yes we are not using require so we are going to have to switch from require to import so instead of is going to be import and instead of require is going to be from just like that and let's try to run this again after a bit of time we hopefully should see that the Ping was sent to the server yes if you see pink to deployment you successfully connected to to be that means that everything is perfect and the second time it even took less time because it was already warm so if we look at this code again what we see is first of all is the connection string that has like my username my password it's recommended to move this one to a environment variable maybe we can cover this a bit later uh but for now it's okay then it creates the going to be client and when we execute the function run it's connecting to the client uh the client is connecting to the database with a name admin and it's executing the command ping and after it uh sends the Ping and receives it back if it doesn't um if it doesn't throw any error we simply consol this one and at the end we are simply closing the the client with database client so that's that's in a couple of words what's happening here let's go ahead here and do review setup steps connection string done okay perfect let's go ahead in the deployment uh under deployment and under database let's see what we have here uh we have a cluster one so let's press cluster one to see what databases do we have in this cluster uh if we look under collections in mongodb we do not have uh we do not have tables we have collections uh here we have actually maybe we should work with this sample movies what's this this is a sample database for us to interact and work with it's called sample mflix it has comments it has movies so our plan I think is going to change very fast because we have a lot of data here that we can work an interact and maybe we can even add uh and work from here as I see it's a database of movies it has information about movies poster title language and so on it has uh users n Stark that's good Robert Bon and it also has email and password oh I'm pretty sure n star can we actually with Alexandra started rewatching Game of Thrones if you're a fan of Game of Thrones let me know in the comments the second time watching it it's like really nice like you you understand like a lot more of the details there but anyway so we have users we have comments I think we are going to be able to query and add comments which is nice so yeah let's go ahead and use this sample database and to be honest I really hope that you also have this sample database and you're going to be able to to follow along so Atlas please don't remove this sample database in order for this tutorial to be relatable in future as well anyway Let's uh let's try to connect to this sample database and and and and send some queries so the name of a database is called sample M Flix so let's go back in our application and what I will do here is in our run function instead of connecting to the database with name admin I'm going to connect to the how is it called sample sample underscore mflix right that's the name yes then the command that I want to send there I don't even need uh to send a command I want to access a collection uh and the collection that I want to access has the name movies movies let's do find and let's the response get let's do here movies equal await collection movies find now if I'm going to console log here movies let's try to run again this index.js file to see if we fetch correctly the movies we see something that's already good uh but we need need to do find and the response of a find is going to be a cursor to be to transform it to array I think we have to do two array and that will transform it to a normal JavaScript array now if I'm going to execute it again we see an array and a list of movie that was read from the database great success isn't it all right that's perfect so that means that right now we can connect our mongodb we so far we have connected to well let's do it again so far we have created a mongodb we have hosted it with Atlas and we have connected to it from our nodejs server the next step is going to be to uh provide this database to our graphql uh end points or resolvers in order for us to run mongodb queries directly from our resolvers for that uh we are no longer going to Simply run this function but we're going to do the next thing let's do it like this client client client wait client connect mhm so what I want to do is I will rename this function run to setup database the setup database should go ahead and connect connect the client and we'll not send any requests we'll simply return the client I don't want to close this connection because I need the connection open as long as our server is uh is running so I'm going to remove this uh finally maybe I'm going to add a catch method here in order to catch the errors and I'm going to Simply console log error connecting to that database and let's go ahead and remove this run from here and what we have we have a function a sync function setup database that we want to export so let's go ahead and do export or let's call it here export a sync function setup database okay now we need this this client we need it inside where we need it somewhere inside you uh in the resolvers of our users for example when we call create user we need the client in order to insert it to the database so we might try to call it here uh for example uh setup database to get the client but the problem is that this setup database is going to be called too often in a lot of mutation in a lot of resolvers it would be better to call it only once and provide the the database or the client of in database to all the M uh all the resolvers for some kind of a context to do that we can easily do that inside our graphql index because in the when we create the schema here after the resolvers we can also provide here a is it here no it's not here it's actually in the server.js where we create yoga when we create yoga besides the schema we can also to provide here context and the context can be any kind of um it's an object containing any kind of fields like hello and the value will be world what context uh I think the context should be a a function that will return an object right I don't know why it doesn't like the schema but yeah hopefully it's just some some typescript but anyway the context will return an object and this context is going to be accessible in any resolver of our graphql uh in our graph qu resolvers to demonstrate you this let's go ahead in our model user and when we call create user we can get access to the context as the third argument so remember the first one is the object the second one is the argument and the third one is the context if I'm going to go ahead and do console log context here and when I'm going to run this create user fail to fetch what's happening fail to run directory import um yes but where do I do that oh in my user I mistakenly imported that but I don't need now if I execute and check the logs we see the the context and the context has a lot of things it has information about their request like headers uh about the you the yeah information about the request like the body the headers that was included the cookies and at the end it also has our custom field that we provided through the global context that has the hello world perfect that means that through that Global context in the server.js we can provide here the the database right to do that we're going to have to import uh setup database from mongodb here from index and let's go ahead and do const uh client equal setup database and we're going to call it and because it's a synchronous we're going to have to await and because it's a synchronous we're going to have to make it a sync okay now we can provide the client here instead of hello I'm going to provide the client setup database uh setup database will return an object with client so that means that means that in our server we're going to have to to probably destructure it from there but sometimes it's not going to be available so you know what setup database in the setup database when we catch the error let's return an empty object like this so in the server yes it's working now from our user when we from our models users where we con cons Lo context let's conso context. client let's try to execute and we see that indeed we have access to the client and we can do the same thing as we did before we can do client dot or context. client dot uh is it database database is how is it called sample underscore mflix mflix dot collection collection with a name movies dot find do to array so the same thing that we executed before let's see if we can get here the the movies so const movies equal a weight all of that uh because we have a weight here we need to provide specify that this resolver is a sync and in graphql we can have a sync resolvers no problem let's go ahead and do console log movies to see what's going to be the response if I check it here and execute it again client database is not a function I think it should be let me check let me check in overview where was the documentation of connecting here connect drivers it should be DB not database so it should be client. DB now if I'm going to execute it yes it has information about the movies so that means that now we can access the database directly from um um from a resolver but I don't want to always have to do client. db. samples and even like collections let's go ahead and in the uh index besides the client let's also do the DB which is going to be client. db. uh moviescore mlex right mflix and not movies but sample M fakes and also Let's do an array of collections maybe it's going to be easier like it's going to be um we can do here const DB is equal to this one and now we can automatically send it like this and collections will be what collections do we have there let's start with users right in the collections users and movies user users and movies let's start with two collections users is going to be do collection users and we have a collection movies which is db. collection movies so now from our setup database we are uh exporting more things we're exporting the whole client that in some cases we might need to send like some pin commands or so on we are exporting the database that is uh connecting specifically with our sample database and we're also exporting like to to make our life easier we're exporting some predefined collections so in our server here where we have client let's maybe do uh here and let's expose it as and the is going to have collections should I simplify this to call or maybe directly like users and movies not to have to access like a lot of things I'm going to do users it's do movies and it's going to be much easier right um let's see that in action so if I'm going to go to our models user instead of taking context. client I can take context. and after that instead of database collection these two rows will be replaced to dot movies context movies find and I can also destructure right away from here instead of having to work with context so now movies is movies. find to array if everything is working fine running this query in the terminal should display us a list of movies yes it does uh perfect so this was the basic uh configuration of our database let me go ahead and do git add git commit uh set up mongod DB and uh we're not done yet because we have to properly Implement like all our mutations to create users and so on so let me know if you have any questions so far how is your day going very good very excited about this one how are you anyway let's go ahead and continue and uh let's start with some crude operation for the uh for actual users uh for crude we have first of all we need to get a list of users right uh to do that in our query we already have the user let's rename it to I'm going to leave it user but the first one is actually going to be a list of users that is going to be users and in return it's going to return an array of user the array should be required but the values inside it maybe shouldn't or maybe we can even make it required like this so let's go ahead and before we implement the mutation let's check the type of our user to make sure that it matches the same type from our mongodb if we look in the mongodb for our sample data in our users we see that it has an ID of type object ID I think in this case it's not going to be an integer it might be ID but we're going to see let's make it required it has a name n Stark name String it has email also string and it has a password I'm not going to hand um worry about the password so this is our type for the user let's go ahead and implement the resolver for our users query if I go into the query we have the first query should be users let's start by simply returning an empty array an empty array is going to be a valid value because it's an array and it doesn't have anything there I'm going to go back to our graphical interface I'm going to refetch the graphql and I'm going to start from scratch by defining a query my Or List users and this query we call users and users is going to be an array of users and here we need to get the ID name and email I don't have any variables yet so let's remove them from there and let's execute the query perfect we see an empty um array now what we have to do is we have to when executing this one we have to query the data from from users database uh I'm looking if they have like some some kind of a documentation here because I think they did view project options no anyway so again what we need to do here when we request a list of users we need to execute a find query on the user database so for that we need access to the database we remember that that database is the third argument so the first one is object the second one is the arguments and the third one is our context from the context we know that there is the field that has do users so what we can do is we can write away go ahead and return do users. find and Van due to array if I return this one and if I'm going to go back here to execute it it's going to take a bit of time and then what's going to say of course some error because why because cannot return null for non nullable user ID yes I know why and the thing is that the ID yeah the ID in is underscore ID it's not just ID so what we have one option would be to go ahead and uh re in the type definition instead of ID have underscore ID and let's try it like this again cannot query field ID because we need underscore ID here and now it works but sometimes I don't want my database or how we co we name our fields in the database to influence how we name the fields in our graphql API I really want I prefer having just ID here so what I can do is I can provide a simple uh I I will go back to having ID like this so what I can do is I can provide a simple resolver to this ID telling graphql how should we get ID knowing the data about a user so I'm going to go into the user I'm going to say that the ID will be resolved based on the information that we have in the previous resolver so the object will have that under sore ID so basically what we are saying is whenever we want to request user ID take it from the previous one the the underscore ID this way if I'm going to refresh it's going to work if I'm going to send we have ID here as a normal string and not underscore ID this is a very common one and sometimes you want to make sure that you I are either accessing it from object uncore ID or if it's null you can access it object. ID so no matter if a previous resolver will are using under sore ID or ID we are still going to take it from there and here you can simplify it like this and you can even do it like ID underscore ID and then return either underscore ID or if that is null ID does it make sense or is it bit confusing if I execute come on okay aric is good so here we have it a lot of users maybe even too many users so let me check uh mongodb dogs crude uh the read operation find I want to limit users find limit query documents so if I will do here find and then dot limit for example 20 is it going to give my me the first 20 users and it shouldn't be in the create users wait a second uh this one shouldn't be even be here at this moment it should be in the users here find. limit 20 let's see now if I execute not sure why it's taking so much time yeah the second time is much faster oh yeah probably it's because uh it when I do some changes it reconnects to to the that's why but now it's much better so what we can do is we can continue we have the list of users the next the next query is going to be user by ID so we have it here but we need also an argument we need the ID of type ID which is required and only van is going to be able to actually fetch it from Mongol let's go ahead here and we are going to have the object but from the arguments now we need the ID to know what is the idea of argument and from the context we need so having let's go ahead and return do users and to find one User it's literally find one and here we're going to provide the ID that we are trying to search uh let me double check the documentation for Mong be crude read find and where is find one where is it find one actually I should look at the version six uh does it have a search somehow to be honest not the best documentation quite no GS DB find one okay so I think there is no f one actually okay so it's not find one most probably it's find and here we need to specify the filters that we want to provide so the value of the fieldcore ID from mongodb should be equal to this ID that we get here most probably it's not going to work uh because we need to transform into ID but let's check it out so after find uh I think we want to [Music] do boy I don't need to array I need to csor uh to array let's see what other method the cser next no no no skip size pretty map limit hint does it have like first anyway I can do maybe dot to array and then at position zero so let's see now if we send this request I'm going to go ahead in here let's refresh and I'm going to remove a query for list of users I'm going to copy one of these IDs because I want a specific user where V ID is going to be equal to this one and back I'm going to get V ID and then name if I search it's null yes because uh most probably we have to transform V ID from a normal string to an object ID to do that I think we're going to do a new object ID that we imported from the Declaration Mark deprecated here should it be with capital and let's import it from object ID oh boy why is it deprecated and it's not even working let me try to do a console log ID just to make sure that we get the right ID here we get this string so I'm going to try to manually in our database go ahead in the filter say ID is equal to v string will it work apply no but if I do object ID and then this string apply it works so maybe I shouldn't do a new here just simply object ID no it's a oh wait oh [Music] boy let's see let's see let's see didn't work with in quite a while query insert not I need maybe even insert uh query uh let's check the nodejs item this is inserting specify equality check status okay but I need to check the ID the [Music] ID none of them are specifying V internally wait a second collection find one method also performs a r operation to return a single document internally collection method is using find so find with limit one that's good so I can do find one and I don't need to array not sure if that is going to solve because that's not that wasn't our main problem but anyway let's see H okay should be new here const user equal uh wait and here return user if I do right now now it works weird but previously it was not I simply return This Promise yes it works okay perfect perfect perfect so but what's the problem with this new object idea do you save it it might also work like this no it doesn't but if is deprecated what's the solution deprecated in use static create from time to set a numeric value from the new object ID what input [Music] ID no but my input is not a number my input is a string so this one shouldn't be deprecated because if I do one two three it's not deprecated but now if I do here it doesn't know that it's a string so the thing is that it's a string so no worries that's the right way to do it okay perfect let's do like this and yes we have two queries ready to get a list of users and to get one specific user so if I do now with this ID we have net Stark perfect uh what would be the next step next step is going to be uh to create a user and to create a user we need uh a new user input and in the new user input we will not have age but we will have a mail for example with a string like this so let's go ahead in the create user mutation uh what we need to do is we need to insert this to the database so we're going to have to uh call insert let's look at the documentation [Music] again getting lost here crude operation insert document insert one so insert one document and what will be the response Behavior if a field okay the ID will be automatically created this is an example to insert one the operation Returns the following document acknowledge and inserted ID so the response right now yeah let's do it like this let's do con uh response is equal to await do uh users do insert one and here we will specify the user input because the user input has the field that we want to insert the name and the email the ID doesn't have it but if we don't specify it it's going to automatically be uh generated for us let's go ahead and do a console. log uh response here to see what's going to be the response now let's go to our Ruru Ruru Let's uh refresh and let's define a notation uh new user the new user will have a variable called user of type new user input which will call the mutation create user that has a field user where we will send the variable user back we want ID maybe name maybe email now in the variables we need to provide here the user with name MIM come on V and the email like this so what's going on the new user input is required yes let's try to execute this query create user it did something not really sure what it did cuz it was supposed to give me back one but anyway we have this F1 and here it's F1 What's Happening Here create user I'm not expecting to see this one here but if I go to the Atlas And if I'm going to look for an object in the users with this ID apply I see that it was in introduced but why is it return correctly here can you explain because I don't understand H what create user create user create user I might might understand where everything else is being taken from but how does the ID because ID I specify here that it's ID that's very weird and not expected let's console log it two times at the top and after insert if I send it now it's unexpected that's correct so yeah this is the user that is coming from the input duplicate key error collection oh it has the same email so if I do VM one to three send oh boy why does it work because as you can see that's again very weird the user that we are sending here to I'm conso loging it at the top I'm conso loging it at the bottom this user is being changed at the top it only has name and email at the bottom it has name email and ID okay not sure if that's a bug or a feature but usually how you would do is you would take basically the response the response has the inserted ID and you will say that hey ID is going to be equal to response do inserted ID and then the rest of a user but anyway that's good it works we can create users we we can insert them in our database one two boom it's there and it has an ID if I check if I create a new query here for query get user and I get here user with ID the one that we just created and then take name and email execute it we see that it was exactly the one that we previously created in this query so okay that's good that means that we have two queries list of users get user and create user mutation all working perfectly um the next one would be uh the easiest would be delete user so delete user is going to first receive the ID of type by D and it will return a Boolean true or false now let's go ahead and Implement that delete user mutation after create user where we have it here delete user is going to be an a sync [Music] function that is going to do the following is going to a wait Mongol but we need the so I'm going to do underscore or let's do OBG args and from the context I'm going to take and so let's do do users. delete delete one does it have a delete one let's check let's check with documentation [Music] for uh cude operation delete documents insert manyu delete I don't want delete all only one document that matches a condition delete one yes delete one make make sure you call delete one because if you call delete without any filters it's going to delete all users from a database if you call delete one even if you don't provide any filters is going to delete maximum one and the first one that matches the one that we want to delete is going to have a ID that matches the object ID that we take from the arguments so in the arguments we're going to have an ID let's pass it here so this is going to be like this and let's return true but does this delete user return anything uh index a see could delete many delete one what does it give back promise call back return returns promise if no call back pass anyway it's going to return something but we're going to consider that it was deleted so let's go ahead in our this one uh when we query get user with this ID everything is going to be okay let's go ahead and add a new tab here and I'm going to copy the mutation from new user only this time is going to be called delete user uh I'm not going to have any variables here but I'm going to call delete let's refresh to get delete user and here we need to provide the ID and delete user doesn't return an object it returns one value that's why I'm going to remove it from there and let's provide the ID of this one this user with d8 at the end so d8 if I execute delete through if I go back to get user and search it again we see that it disappeared and I really hope that other users are still there so if I'm going to do here instead of user users ID name I hope that they will still be there yes the rest are still there so if you don't really like Joffrey Baron you can take his ID you can go to delete user can provide it here execute it uh execute it then come back run again the query and there is no uh I already forgot how is his name jofrey yes it was deleted so that easy we have also the delete operation now the last one for our crude operation for our crude operations is the update an update user will be a mix of create and get because we need to know the ID of the user that we want to update so that's going to be ID but we also need to know the new user input so new uh data or new user this new user you can either have a separate input field if you don't want to allow overwriting some fields for example if we don't want to be able to overwrite email we can copy this one as a update user input and delete the email to allow the user only to update his name that's also possible but you can reuse uh different inputs as well uh so let's let's not say new user but update let's just say update so the update user will have two arguments ID and update let's go ahead in our mutation and create update user that is going to be an a syn function um the object we do not need so we can call it OBG but in the arguments we're going to have both ID and also the update from the context we of course need the and what we will need to do is we will need to do dot users dot update one let's check the documentation of update one in there where CW operation update document update one the first one is a filter the second one is update okay so iner update one the first one yeah is is a filter the first parameter is the filter how do we want to find the object that we want to update we are going to find it by ID by creating a new object ID from the parameter that we receive from the argument and the second option is the updated is the update so there I'm going to provide the update like this and back we're going to receive what uh dating multiple and in this case we are actually um we're replacing the document all together uh what's going to be the return return come on let's just see con uh const response equal to this one and let's consol log response response and in update user what do we say here that the return will be update user we didn't specify what's going to be the return the return should be user so let's go ahead uh here in our Ruru let's get a user for example let's create a new user for example by like this doesn't want V one two three four five yes now we have his ID we can go ahead and search for him here if we check by him with a name by let's now go ahead and Define a mutation called update user where we will call the update user method and back we're going to get ID the name and the email the update user needs the ID of the user which is this one and it needs the update which will contain the updated name for example V one 12 three now if I execute uh something is not working yeah because I didn't provide here any Val variables I'm hard coding them here uh and yes I'm not returning anything but what I get here in the console is update document requires Atomic operators duplicate key no no no wait a second uh requires Atomic operators invalid invalid argument what is the update there console log update but I don't want to replace actually because I want to keep the email there so I think I'm going to have to Simply do a set in the update here we see that we need to update operator so it should be set for example uh instead of update I'm going to have here set like this yes and what do we want to set we want to set field value so the field is name the value is update. name now if I execute this one again it's null but in the console we see that the modification is one uh okay modification one upate one and I can return back not sure I think in the update one I can also specify that give me back the updated uh object but I can simply do a query which wouldn't be very optimal but still it's going to work so Mongol users do find one let's find one where ID is our object id id so now in this situation not con but return this if I do is going to first update it then it's going to return so if I update this one to back to Vadim it's going to update it fetch it again and return it here uh like this and now it's updated in the database as well perfect perfect perfect so that means that we have all the crude operation guys for our user model uh okay that was a lot uh if you want to continue I highly encourage you to uh do the same for the rest of our models like movies comments and so on I'm going to go ahead and do a git ad git commit uh users cude users perfect um I only want to show uh one more thing I want to show how we can create relationships between things for example in our database we have comments and a comment has uh has email right why is it email and not user ID users sessions user ID movies cost but anyway comments have email so they only know the email of a person who commented this but how can we connect them together in order when querying the comments to know also the name of a user to do that uh let's first of all create a query for the comments so what I'm going to do is in the uh graphql I'm let's create a new folder comments here and in the comments let's create or no in the models like wait I'm already tired but let's do it uh together so in the models let's create a file here comments. GS from the comments we need to export two things similar to how we do here we need to export the type def from the comments export type Def and also we need to export the resolvers now in our index we need to import them in the similar way as we imported them from user we need to import them from comments so the type def as comment and resolvers as comment resolvers comment resolvers comment and common resolvers now we need to give them here in our schema after the user we're going to have comment and after resolvers we're going to have commment uh resolvers now let's go ahead in type definition I want to define a type the type of our comment that has what id uh let's actually do underscore ID it has text of type string and it has it has email let me check if it if it's actually connected because if I go ahead and check a user with this email will it find it yes it finds it so email string now I also want a query type uh query called comments comment it will give us back an array of comment in the resolvers we need to define the resolver for our query called comment and this resolver will uh they have object arguments and the context where we can get the from we need to define a new collection so let's open index here and the same way as we have users movies let's define here common comments db. collection comments now from the here we can return do comment. find we're going to find a lot but we're going to only limit let's say the first 20 uh and let's do to array now let's go ahead and see if it actually works I'm going to refresh this one and let's create a new file here query comment let's do comment ID text and email if I do that we see at 20 comments from users but we know that logically like in a graph a comment is posted by a user in our user interface we might display users with where Avatar we might display comments with user information with their avatars and so on so what we actually want is we want to be able to query here the user with his name and password or name and Avatar and so one we haven't defined that a comment H can have a user property let's go ahead and try to Define that right now to do that on the common type we will say that besides all the fields here you're also going to have another type called user of type user now if I refresh this one I can go ahead and do user not sure if it's uh going to refetch because it might not know the user here but no it actually works so we can query the user with his name but at the moment the user is n because we didn't provide the resolver we didn't tell graphql how knowing the information about the comment how should I grab the user well logically is you have the his email in your data go ahead and query it from the database and take all the information about the user from the database to do that we have to provide a resolver for the type comment over f user let's go ahead and after the query Define here the comment type and the comment type has the user field that needs a custom resolver the first the first parameter is the object the second one is the arguments and then we have a context with this is where uh the object is actually uh helpful because remember as I was saying like to get the user we need to look at the parent object and take the email from there the parent object is actually our OBG here so we can take from here email and it's going to extract the email from the parent object now what we can do is we can look have a look at how we queried in the user for getting a specific user in the queries of a user we did this one so we can do the same here in the comments return users find one ID with this object ID where I'm going to import it from there but actually it's not finding one by ID but it's finding one by email so I don't even need the object okay that's all we had to do we have to spe speci ify knowing a comment how should I get the user and to get the user we're going to query the database and find the user with that email if now I'm going to do it like this we're going to see that now all the comments they have also user information here John Bishop name and so on and the cool thing is that you can have access to anything here like his ID his email and if he has uh relationships for example if he has like I don't know friends you can do a lot of nested queries like this all the way so this is actually the power of graphql and that's why uh now any time we specify that something we'll return a comment we will only we will always be able to get the other relationships for that comment because we Define it one on the comment type and later it can be used anywhere for example a post can re can have comments and the comments can have users so everything is interconnected so that was our relationship between this one so let's do git add git commit comment uh connection with user perfect and you can do have a same connection try to do it yourself on the user to have give me all the uh give me all the comments that this user has posted actually let me try to do it maybe we're not going to be have time to deploy this API but the the backward connection is going to be important so on the type user I want to say that hey I want sometimes to be able to query the comments that that user provided so it's going to be an array of comment now we need to specify how should we get the comments knowing a user for that we're going to go into the M uh resolvers of a user let's provide the resolver for the comments we're going to get the object we're going to get arguments and we're going to get the context with and what we should do is I'm going to find um let's take this one for example and in the comments I'm going to do do not users but do comments I want to find and I want to find comments where email is equal to the email of this user the email of a user we can take it from the object because this is the par the parent of a comments is a user so it has an email we're going to take it we're going to filter find only V and we're going to limit to 20 now if I go here we can go ahead and say give me for example get user with name and email and for this user I want to see all the comments that he has created so it's going to be text and also email just for us to confirm that it's the same so if I run this I see that there are no comments why because comments is it like this comments find email console log email oh yeah yeah yeah wait a second because there are no comments with my email I'm I'm no one but if I'm going to take the email John Bishop uh not not the email the user ID of John bishop and if I'm going to go here and say give me the user with this ID and all his comments we're going to be able to see information about him and comments that are only related to his email usually you don't need the email here so yes that's how you can create relationships and you can have circular dependencies for example for a user we took the comments and a comment can take information about the user so you can do that again and this will give the usern name email comment and for every comment is going to also have his username and email in this case it doesn't make sense because it's circular but I wanted to show you that you can go very deep into into to your um fields that you're querying here and that my friends is our G commit minus M user comments connection uh yeah that my friends is the is our graphql API to be honest we took a little bit more time than I expected uh to to explain everything because we also covered all the crude operations for our users also showed the relationships and so on so there is not really enough time to for us to deploy uh This Server uh my plan to deploy this one was to deploy it to AWS ec2 which is a cloud compute service and instead of that let me actually try to uh show you in what tutorial we have done that because we have worked with um let's do live streams let me remember in which tutorial we deployed something on AWS ec2 it was it was this one so if you scroll down until you see deploying Twitter backend on AWS ec2 and AWS RDS the process of deploying the Twitter backend to ec2 is going to be exactly the same that you need to deploy the current server because our graphql is server is nothing more than a simple nodejs that can be started with uh running node uh on the server you're of course not going to watch you're going to Simply run node server. GS uh and of course on the server you most probably uh you're not going to use node directly but a tool to run it uh permanently called pm2 and pm2 is a process manager for node GS which is exactly which is used in production to make sure that your application doesn't stop working after something crashes so pm2 is going to inspect it is going to analyze it's going to restart it's going to monitor it so by simply installing it on your virtual server and then running pm2 start application is going to uh be let's say production ready and monitor this uh so yeah check out that tutorial because it's exactly the same um and if you have any questions about today's tutorial about graphql and so on let me know sand is asking when will you make a complete serverless application with no JZ and Lambda as ec2 is outdated um if guys I'm not sure let's see how many of you are interested in more of the backend tutorials if you are interested let me know and I can do more of this in the future because on this channel we focus a lot on mobile uh applications and I know that that's what you guys enjoy but me personally I love working on the backend uh I was actually more of a backend developer uh when I was working at Amazon and so on so would really love to to prepare more tutorials for for back and especially especially around serverless uh application using Lambda functions that would be uh something exciting for me to to cover hav can you do a voice uh a project on voice call yes we can try ID to string doesn't he know that he is live what happened uh he not looking at the chat sorry guys I was so focused on that one Mong bu to generate for every collection created why are not using uh because I try to cap it very simple Nest gs1 love all right guys thank you very much for joining I hope you found this valuable if you did make sure to subscribe to the channel we're very close to hitting 100K subscribers and that would mean a lot to us and yeah uh we have prepared a lot of new tutorials coming next following weeks so make sure to also turn on a notification Bell so YouTube notifies you when we go live uh that was it for today uh I will see you next week
Info
Channel: notJustā€¤dev
Views: 5,751
Rating: undefined out of 5
Keywords: vadim savin, not just development, notjust.dev, react native live coding, live coding, react tutorial, react native tutorial, react native for beginners, React Native, step-by-step tutorial, API development, GraphQL schema, queries and mutations, deploying GraphQL API, NodeJS tutorial, GraphQL cloud deployment, GraphQL API tutorial, learn GraphQL, NodeJS for beginners, GraphQL fundamentals, database integration, GraphQL resolvers, GraphQL types, nodeJS tutorial
Id: UYQSVH6B1k4
Channel Id: undefined
Length: 220min 24sec (13224 seconds)
Published: Sat Feb 17 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.