#5 GraphQL + MongoDB | Build a Complete App with GraphQL, Node.js, MongoDB and React.js

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi and welcome back to this serious we started implementing our graph QL API we added the event type now it's time to also add a database behind the scenes so that our data is not just persisted in memory as I'm currently doing it which is of course not a great solution for a real application but that we instead persist our data in a real database now in this video I'll use MongoDB and we'll set it all up from scratch and manipulate our code such that we really use that database of course you could use any database though now let's implement it step by step as I mentioned I will be using MongoDB here - well as a database for this project and you could use a my sequel database you could use poast where as sequel you could use our new sequel databases so graph QL really doesn't care it works with any database because we will write the logic to interact with the database that's not built into graph QL as you will learn now I'll use MongoDB because I really like it it's really fast has good performance really flexible and if you want to learn more about MongoDB specifically I got a whole video and complete course on MongoDB and you'll find links to both in the video description and these are awesome resources to learn everything about MongoDB now here I will specifically use the cloud hosted database solution MongoDB offers MongoDB Atlas because I don't want to take care about administrating and setting up that database now for that you will need an account you can click on get MongoDB and on that page there you can choose cloud or that is actually selected by default and here you can sign up and you need no credit card for this you can start with this for free so you can sign up here and you will thereafter be prompted with a screen where you can set up your first MongoDB Atlas cluster and there you can choose all the free to your options and you will end up with a cluster and here I already am locked in that should look something like this so this is the screen you see after you configured and started your cluster with all the free tier options so where you don't pay anything and as I said you won't even need a credit card there for now once you have that cluster up and running we of course want to connect our application to it and to do that we need to do two things the first thing we need to do is manage our security settings here on the cluster such that our application is able to connect to the database because not everybody should be able to connect of course the second thing which is important is that we also use a cool a driver in our application so in our graph QL API which is able to query the database because we won't write queries ourself in a special language like sequel hazard instead we will use a tool that exposes methods we can execute against the database and I will walk you through all these steps now in this video let's start with the security settings here on the security tab and there you should make sure that you have at least one user who's either an admin which who is basically able to do everything or has read and write any database rights which means this user can read and write to any database you have on your cluster because on this cluster you can have multiple databases we will only use one but you can use a user with these rights now on such a user you want to set your own password or auto-generate one and I will quickly show it so that I can copy it because we'll needs that later and I will click update user to use that new auto-generated password and the other thing we need to do is that we not only know the user credentials but we also have to decide which servers can connect to that database cluster server here and there under IP whitelist I got a bunch of IP addresses here because I used this cluster for other projects too you probably have none of these addresses there what I want to do there is I want to add an IP address now I already added mine so I will quickly delete it here and thereafter I can click on add IP address and now choose add current IP address and this uses your local IP address so if your local machine where I will or we were we will do the development if you later deploy this API on to another server in the web you will need to use that IP address or that IP address range of that web server of course here I will confirm to add my local IP address and now I'm both allowed to connect from my low host:2 debt MongoDB server and I will have a user who has all the right access rights with that we can switch back to the application and now in here we need that other part that MongoDB driver that package that allows us to interact with MongoDB now here we could use the native MongoDB driver a package managed and maintained by the developers behind MongoDB but I will actually use mongoose mongoose is a third-party library you can install through npm which in the end builds up on that official MongoDB driver and adds extra convenience features and most importantly it allows us to work with models so it allows us to manage our data through javascript objects and for example when we then save such a object or execute certain methods on it then this automatically is translated to a query against the database which persists the day that there - or fetches it from there and therefore I will install this through NPM with NPM install - - save and then it's Mongoose like this now that installed this mongoose package and with that we can now restart our server here with NPM start but I will actually not do that instead here I will add a node maaan dot Jason file and this will automatically be used by that node Mon tool we use to start our server and there we can add some configuration for that node one tool and I want to pass in an environment variable which basically holds my sign in credentials for the database because I can then easily swap them by just editing them in that file if I later were to deploy that or to be precise we wouldn't even deploy that file so we can basically set up our credentials for our local development environment and later easily use our credentials when we deploy the app for that in here I need to add a ends key and in that end object I can now set up environment variables which will automatically be injected into the node.js application when it starts through node Mon which we can then consume inside of the node application there I will add a user and here my user name was Maximilian of course you probably have a different user name and I have password and that is that password I generated and copied with that edited this will automatically be consumed and now in App Jazz we want to connect to Mongoose for that I'll first of all a to MongoDB fruit Mongoose for that I will first of all import with require import Mongoose here and now we can use Mongoose to establish such a connection I'll do that towards the end of this files file here there I will use Mongoose and this has a connect method now disconnect method first of all needs a connection string which basically is the address of our database cluster or a server and we can get that string if you go back to the cluster to the overview and click on connect there and this will open a modal there we can choose connect your application and then choose that which requires MongoDB 3.6 or higher this SRV string copy that string and add this here and now we'll actually use backticks here to create a template literal because this will allow me to now dynamically change my username and my password here so or for the username I will use and now we can access this at this environment variable as we always do it in nodejs with process dot n dot and then here I have user so does first environment variable we added a second ago and I'll also replace the password here of course with process and password okay and now we construct this connection string to connect method that actually gives us a promise and here we could fail so I will just log any errors we get for example you could fail if our cluster is down if the credentials are incorrect if our local network connection kind of is broken we succeed and in this case in the van block in this case that we succeeded I want to start up my server now you could also have a set of where you always start your server no matter if you connected successfully or not and you then have some logic to retry the connection I will take this route here and now with that let's run NPM start to bring up that node one server and try connecting to MongoDB and this succeeded we can't ignore that deprecation warning here we got no error so now I'm successfully connected to MongoDB to my cluster to my database and now it's time to actually start adding some logic to interact with that database because that's far in my resolver here in this file create event for example I only store this in my events array here and that is just in memory now I want to use MongoDB and I want to use that strongly typed modeling feature mongoose gives me therefore i'll add a new folder here which i'll name models and in there I will add an event dot JS file and this will be a model a JavaScript model created with that mongoose package because that package is all about using models to manage data so that we can easily implement a model of view controller or in our case a model controller endpoint approach for this I will also import mongoose in here in this file with the same syntax we used in app j s and then i need a specific feature from the mongoose package which is called schema and i will add a capital ass here because whatever i'm going to access now will actually be a constructor function and I get that from Mongoose there is this schema property and again this points at a constructor function which I can use to generate new schema objects schemas are the first important building block added by Mongoose because we can now create an event the schema here and you can name this however you want of course by instantiating this with the new keyword since it is a constructor function we can create a new object with it with the new keyword and then we pass a JavaScript object here to the constructor function where we define the structure and this allows us to define the structure of an event object which we can then reuse throughout our entire app and where we then are guaranteed that every event object will look exactly like this now how should an event look like well if we have a look at our app J's file then we see that an event here in our graph QL API has an ID and this will actually be added automatically by MongoDB among us so we don't need to add that then we will have a title a description a price and a date and later I will also add more once you add users and we want to connect an event to a user and so on but for now we can go with these four fields now back in our event model in that schema here we simply add a title property here in that object we pass through the schema constructor and now I could add string here to define that this will actually be a string and Mongoose or Longwood EP then we'll respect this and we'll store the data as such and will yell at us if we try to use different data but I will actually pass an object here because I can then configure this in greater detail and there we have a type property which I set to string to make clear yes the type of the title property will be string but it will also add the required property to make clear it's not just a string it also is required so it must not be null and that of course also fits our graph QL schema which is otherwise not related to the MongoDB schema by the way there I also have a non nullable type because I added that exclamation mark and of course we kind of want to keep our MongoDB schema which affects what we save in the database and our graph QL schema which affects what we work with and what we return we want to keep these two in sync right because we say in graph QL this will never be null and we do allow null values in the data we store it in the database then we have a mismatch which will ultimately lead to problems so here I have my title I will now also add my description here and on this description I will also set the type to string because the description will be a text and this will also be required them there must not be an event without a description in Maya of course you could tweak this to your likings I will also add a price here and dad will now actually be a number there is no float in JavaScript there is just a number integers and floats are both combined and that number type and this will also be required now here I will also have a date then and the type here will be date unlike graph QL where we had to use string we do have the date type in MongoDB so we can use it here and of course will be our duty to convert this when we pass it back to graph QL to the front end and to the database and this will also be required okay so this is my schema for now now the schema alone doesn't help us we now need to create a so-called model based on a schema the schema kind of us like our plan you could say the model then is the blueprint which incorporates that plan which we can then use to create objects with which we actually work in our application we create such a model also with Mongoose by calling the model method and this takes now at least two arguments the first argument is that the name of the model and here I want to name this event and this has to be a string this will affect collection in which just gets stored in our MongoDB database and it will also affect other things by which you can access this and so on now the second argument here is a pointer at the schema we want to use for that model and here I wanted to use my event schema of course now this creates a model but in this file it's not that useful to us we want to use it in our files and therefore I will export it with the notes as export syntax which is module exports equals this model and now we can import that file into our files and consume our model there now with that model setup we made a huge step forward now in app says I want to change one everything here I also need to define in which database this gets stored because we connect to a cluster here and actually also to a database in a cluster this is this part here after that slash and if that database doesn't exist yet it will be created on the fly the same is by the way true with mom would you be for all collections and so on it's all created on the fly if it doesn't exist now I don't want to use test as a database name instead I'll go back to my node montt file and in there I will add my MongoDB field and I will name this he when's react death you can use any name you want this will be that the name of the database which will be created automatically and now in App jeaious I can replace this with some dynamically injected value which is process dot n dot MongoDB the name of that environment variable I just added now if I save this it will restart and connect to that database and now any data we save will get saved in that database so there is a lot of work already now let's finally tweak our code such that we actually do save our events in the database and that we do fetch the events from there as well for that in app Jess let's import our own model I'll name this event with a capital e because the Mongoose model created by that model method here actually will also be a constructor function we can use to build JavaScript objects based on our model we defined here I do import it by simply importing from that models folder and there that event file we created and now we can use that event constructor here to create a new event object that we want to save to the database so previously we created this like this with the object literal way here now I will create my event by calling new event using that event constructor generated by Mongoose model and there we now pass a JavaScript object where we pass fields or values for all the fields we defined in our schema so in this case in case you forgot it you can quickly check we got a title description price and date field so basically what I set before already so here we can set the title and this now should be a string and basically I can copy that right because that is exactly what I wanted to pass or store before it still is what I want to store one exception is to date here the date now can be a real date when we save in the database I still will get it as a string but then I expect this to be a string that can be parsed into a date object so I can use the built in date constructor and parse that incoming string into a javascript date object which is then passed on and which will be stored in the database and of course MongoDB then all the stores is in a slightly different format but this is all basically trans transformable between JavaScript and MongoDB and the other way around I then don't want you push my event on to some event array or events array I will actually get rid of that array here we don't need it anymore instead here on this event object since it is based on a mongoose model it's not a normal plain vanilla JavaScript object I can call a couple of methods on that and one method is the save method this is provided by the Mongoose package and save will actually hit the database and write our data as we define it here into the database so here I'm saving this and then I can call then and catch there after because this actually returns not a real promise but a promise like object dead for our purposes works like a promise and then I either got an error which I can catch and where I can console.log the error or where I have some result of that operation and I can console Locke that result here - now keep in mind we also need to return an event object here due to our graph QL configuration which basically tells us when we call create event we return an event and I can already tell you that result will basically be an event object so I can return result here though to be very precise this is like enriched document or an enriched object with a lot of metadata we can return a new javascript object here and use the spread operator to get result dot underscore doc which is property provided by Mongoose which gives us all the core properties made that make up our document our object or event object and leave out all the metadata and then we return this now if we have an error I of course all don't want to return something and there I basically want you just throw that error again so that graph QL Express graph QL can handle that and can return us an error this is our create event resolver here now one important thing is you should return this here so that graph QL Express graph QL actually knows that this resolver executes an async operation at the end and it will wait for this to complete otherwise it would complete instantly and would therefore not get a valid result so we need to return our promise here then we can use the rest of the code get rid of our old event definition here or object creation to be precise with that we should be good to go to restore an event at the database now let's give this a try on our localhost / graph QL URL where we can run our graph QL queries and play around with them and there we want to execute a mutation against create event where we need to pass an event input and there we have a title a test we have a description this is a test we got a price which should be a float so let's use $9.99 for example and last but not least we got that date and here I will open up my developer tools really quick because here I still need to pass a string and I can generate one with the help of the developer tools here by just calling new date Qi so string this will give me today as a string I will copy that close to developer tools and pass that string here and then we should get back an event so of course here I will actually then well for example fetch the title let me prettify that and execute this career and this doesn't look too bad I get back a title now let's look into our MongoDB database and you should be able to do that here from inside that mom would be class review by clicking on collections if you don't have that button there you can search for a MongoDB comm-pass which is a tool provided by the moon would be company that also allows you to connect to your database and then inspect your database so you can download that it's free to use and there you can visualize your data in the database and look into it but here I got that integrated into my well view here and if I click on collections it will load all my databases and all my collections and I actually got more than one database you probably only have the one we are working with I got a couple of databases I'm looking for my on the find databases looks like so seems like I made a mistake here process and MongoDB I probably should have restarted that now that server here because I changed node one Jason with it running didn't pick up the new configuration makes sense now on the finest database which was created here due to my mistake we'll fix this in a second but there we do have that events collection and if we look into that there you should actually find your event which was created a second ago this is the date I just generated the surprise so this all worked please note that the ID was auto-generated it's that strange object ID type which is a special data type provided by MongoDB it's a unique string that is also taking into account the current timestamp with that we got it all working now I'll quickly just stop my server and restart and I'll then execute that same query again and now I will refresh here and now I should have that correctly named database there it is events reacts death my mistake I did restart after changing the node one conflict but the main important or the most important thing is we are able to save the data now saving data is of course one nice thing we also want to be able to retrieve the data right so let's go to our other resolver where we returned the events and it's not that simple anymore instead of just returning some events array which doesn't exist anymore because I deleted it we can use the event constructor like this so without new and there we actually have a couple of static methods so methods we can call on the event constructor function without actually creating an object based on it and one method we can call here is find find allows us to well as the name suggests find documents in that collection so find event documents we could pass a filter so an object where we say find objects where the title is a test for example you can learn more about filtering in my MongoDB course we'll probably also do it throughout this series but if we don't pass anything here it will give us all the entries in that collection and that is exactly what I want and then again we have this promise like API where we can get an error which I want to basically throw or where we get the result in my case my events documents and then I want to return these of course because our events endpoint here actually should return an array of events right therefore in here we could now say return events but just as before the events a day that we get back by Mongoose actually has some metadata attached to it so I will use the map operator here and I will transform every event in that array that is retrieve by MongoDB by into a new object so I will return a new object for every element in events and there I will use the spread operator and use everything from event doc like this and with that I leave out all the metadata and then I can here I'll return this whole operation so that graph QL Express graph QL again knows we're doing something asynchronous here wait for it to finish and don't try to return something too early okay now let's save that let's go back to graphical and let's run a query now against events and there whoops hit enter too early there let's for example fetch the title and this works and now let's all to fetch the ID and this will now actually give you an error and that's good because now we also see how an error looks like we get this errors object and there I get the error that the ID cannot represent this value now the problem here is that special ID data type MongoDB uses this object ID data type and this is something which is not natively translated into a string or which isn't understood by graph QL so we need to translate it into a string now how do we do that well when we return our events here I do pull out all the data in this dark property which Mongoose adds which is all my core event data and now I just can overwrite underscore ID by adding it again thereafter and this will replace the first underscore ID which is pulled out of the document and there I will call event dark underscore ID Q string to be very clear what I want to do here so I will access this document with all its data there will access the ID and it will call to string which is a method which is available which will convert this to a normal string that is then understood by graph QL if I save that I can execute that exact same query which failed a second ago and it now succeeds and here is the string idea obviously this is not just a problem when we get all events but also when I return to generated event there I also want to override the ID with my result doc ID q string now there is a shortcut by the way which is worth noting mangu is also gives us another property we can access event ID like this this is a virtual getter provided by Mongoose and you see it now still works this basically abstracts all this logic away so we can use event ID and MongoDB or Mongoose to be precise Mongoose will actually access the native ID and translate this into a string here please note that I also don't have an underscore here because this really is a different property this is a property added by Mongoose to let us access the ID in an easy way we could use it down there too I believe two or above methods here or both approaches so that you see what's happening behind the scenes and now with that we are able to query our events let's now also add another event again create event with our event input where we have the title just another event the description whoops this is another event where I then also have the price let's say 100 29.99 and where I also have to date and here to keep it simple I will just use that same date from before again and then let's say I want to get that ID back and I want to get that title back and if I hit enter this works proving the fact that we fix that ID error for the mutation to you and if I try that query for all my events again then you will see here I can for example fetch two titles and descriptions of events and I get more than one now I got two events awesome now this was quite a long video but we did at MongoDB here we now work with real data and we store it in a real database in the next video let's refine our API let's restructure it a bit let's work on that schema and let's also make sure that throughout the next videos we also are able to add users book events and so on
Info
Channel: Academind
Views: 79,236
Rating: undefined out of 5
Keywords: graphql, graphql api, mongodb, mongoose, model, models, tutorial, full app, full project, node, nodejs, node.js, react, reactjs, react.js
Id: sOUNgOx0GcU
Channel Id: undefined
Length: 32min 22sec (1942 seconds)
Published: Thu Dec 13 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.