-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Data
In this module we're going to talk about getting data from our API. Now we've started building out a RESTful API with Node and Express. We haven't done a whole lot yet, we've just setup the basic structure and we'll re-cover that here in just a second, but what we're going to do in this module is implement the HTTP Get verb that allows users to pull data from our API. We're going to allow them to pull a list of items or just one item. We'll wire everything up to MongoDB because it doesn't make a lot of sense to have an API that doesn't have some data behind it, and then we'll allow the user to search for items using some query string parameters.
Now if you've been following along so far your code should look something like this. Basically all we've done is we've created a reference at an instance of Express, setup a port, did an app.get to our root route, so that if somebody goes to the root of our API they'll just get a message saying welcome to my API, and then we're listening on port 3000. The only other thing we did is setup Gulp to run our process and notice we have set in Gulp our port to 800 and we did that just so you could see that our application was pulling environmental variables out of nodemon running Gulp (Typing). Now in order to get started with our API we need to setup some routes that define what our API looks like and there's a couple ways to do routes in Express, the first one being how --- what we did here, this app.get, and that's a good way to do it for simple, straightforward routes like this route, but if we're going to create a bunch of routes there's a better way to do it and that's to use --- a router, so we're going to create a router called bookRouter and that's going to be equal to express.Router and that's going to give us an instance of a router and what we can do now is we can use that to define all of our routes and then come down here and do app.use and setup a base for where our API route is going to be, so let's do /api and then we'll pass in the router and that will take care of loading all of the roots up into app.use for us, so that's a cleaner way to do our API routing. Now that we have a router to use to setup all of our API roots let's go ahead and create a couple of routes for our API, so let's do bookRouter.route and we're going to setup the Books route. Now depending on who you are you might want to do Books, you might want to do Book. It really doesn't matter, it's kind of a personal preference thing, but I think Books plural tends to be more standard, so we're going to do Books, and then we're going to setup the get route and this way doing it here I can do .get, I can do .post, and I can set all of those up right there and have a nice clean look. We're just going to do get for right now, so let's just do that. This get's going to take a function that expresses going to call whenever this get route is called, so it starts with function req and res and req is going to be the request that's coming in from the client and res is going to be the response that we're going to send back. For right now let's just send some data back, so we can make sure that this route is working, so we're going to create a var responseJson that's just going to be a simple JSON object, so for right now let's just do hello with some JSON. This is my API, how about that? Let's do that and then we're going to send that back to our client, so we'll do a res.json and as opposed to the res.send that we did down here, this is just going to send a string of text. If you are sending back HTML you might do a res.render and in this case though, we're going to send back a JSON object, so we're going to do a res.json, and we're going to send back the responseJson object. Now before we go any further let's fix this to be passing back the right thing and then we have to start Gulp back up again, so let's do gulp, and that's going to kick off our API and notice how it's running on port 8000. Alright, now with our API up and running we're going to do /api/books and that will pull --- up our, This is my api. Now you might notice that my JSON is nicely formatted in my Chrome window, and that's because I have a plugin called JSONView that I downloaded and pulled from the Chrome store.
Now that we have our API working we want to hook it up to a real database on the backend, so that we can return some real data. Now I'm going to use MongoDB and so you can go into mongodb.org and download MongoDB and get that installed and that's what we're going to use as our backend database. Just click right here and get it started. Now if you have access to the course materials, then you'll find the instructions on how to import our book data into your MongoDB database. If you don't have access to the course materials don't worry about that too much, just follow along and in the next module we'll get to inserting data with post and then you can load your database that way and then come back and double check your get. Now in order to talk to MongoDB we're going to use an npm package called Mongoose, so we're going to kill Gulp, and then we're going to do an npm install mongoose --save, and what Mongoose is is essentially like entity framework would be in the .NET world or any ORM, depending how much your background is. It's going to take the data in Mongo and convert it into JSON objects that we can then use in our application. Now once that's done installing we need to pull that in and pull the reference to it in our code, so we're going to do mongoose = require ('mongoose'). Now that we have that we need to open a connection to the database, so we're going to create a variable called db, and that's going to be mongoose.connect and what we pass into that is our connection strings, so in this case it's going to be mongodb://localhost/bookAPI and bookAPI is just the name of the database that we're going to be connecting to. Now what that'll do is when our application starts up it's going to go ahead and open a connection to the database and hold that for us until we're ready. Now if bookAPI doesn't exist it'll actually go ahead and create it for you, which is extremely convenient for us. Now the way that Mongoose knows how to translate the data that it gets out of MongoDB it uses a thing called a model, so we're going to do var Book = require (Typing) models/bookModel, and we need to go over and create this model that lays out what the data in MongoDB is going to look like. Now that we have that let's go over and create a new folder called models and a new file in models called bookModel (Typing). Now what this is is it's basically a JSON object that lays out what a book looks like, so we start by getting a reference to mongoose (Typing) and a reference to Schema (Typing), which comes from mongoose (Typing). Now once we have a schema we're going to do var bookModel = the new Schema and we're going to layout in JSON what a book looks like, so for example in this case a book's going to have a title, and its type is going to be a string and we're going to copy that because we're going to use that one quite a bit. It's also going to have an author (Typing), which also is a type of string. Then we're going to have genre (Typing) and last, but not least we're going to have a parameter called read, and this is going to tell us whether or not we've read this book, so its type is going to be a Boolean (Typing) and we're going to give it a default value of false. Once we have that we're just going to do a module.exports = mongoose, so --- we're going to load this model into Mongoose, and we're going to call it Book, so we do a mongoose.model Book with --- bookModel, and what that does is it tells Mongoose that we have a new model or a new schema called book, and then we're going to return that in our module.exports, so that back over in our app.js we now have an instance of that book model. Now we already have a Mongoose course out on Pluralsight, so if you have more questions about Mongoose I would suggest you go watch that course when you're done here. This is pretty much all we're going to talk about in Mongoose just so we have a framework, so that we can go and start pulling data and writing data to the database. In order to use this we're going to back over to app.js and down here in our books route instead of doing this we're going to use our book, so we're going to do a Book. Remember Book is just an instance of our book schema that's hooked up to Mongoose and MongoDB and we're going to do a Book.find. Right now we're not going pass in anything, we'll start passing parameters into this find later, but for right now we're just going to do a book.find, and we're going to pass it in a callback and that callback is going to have error and books. If it errors out it'll have something in err, otherwise everything's going to be in books, and so we'll just check that. We'll say if err we'll do a console.log and we'll log the err. Otherwise, we're going to do a res.json(books) and we get rid of that one. Basically what's going to happen here is when you go to /api/books we're going to do a Book.find and just take the results and pass that back to our browser. Now in order to make sure this is working we need to go back over and do gulp, start our Gulp server back up, and then we'll check it in the browser. Our API's up and running because we have our welcome to my API, but let's go to /api/books, and what you'll see here is we are pulling back data from MongoDB and we have a list of books here, so what that means is we are now successfully connecting to MongoDB, pulling back that list of books through Mongoose, and sending that back to the browser all right here in this four or five lines of code. Now we don't really want to do console.log. Instead of that let's do a res.status if there's an error and send back a 500 error with a message that contains the error. That's a cleaner way to make sure that we're showing that there actually was an error in our API call.
What we have now is an API with a get method that will return back a list of books when you go to /api/books. What we want to do now is add a filtering option to our API, so if I want to read all of the science fiction books I want to be able to come up here and do ?genre=Science Fiction and have that filter our list based on the genre of the book, so what that means is when you go to api/book with a ?genre=Fiction Express is going to package up those query string parameters into a nice little JSON package in req.query, and so what you end up with is req.query = and a nice little JSON object with your query string parameters and we're going to use that to filter our list. Let's go back over here and add that req.query into our book query. If we do query = req.query remember that is a nice JSON package that includes what we're sending in. Book.find takes a JSON object as its params for its search, so if we just pass query in here and then our function that will just work as it is, so if we save that you'll see gulp will automatically restart, and then we'll pull our Chrome back up and now you'll see that we are filtering by genre, and I can also filter by author, let's say Jules Verne, and that'll filter for me as well. Now the problem with this is that whatever is typed randomly up here in this bar will filter through and go straight to the database and that's generally not the behavior we want. We'd like to sanitize user input a little bit before we start sending it over to the database, so a good way for us to do that is to come back over here and instead of sending req.query right there we'll just create an empty query and then we'll check to see if req.query.genre exists and has something in it and if it does, then query.genre is going to equal req.query.genre, and that way we are only allowing ourselves to filter on that one piece of information, so if I come back over here and I hit Enter now you see that it's not going to filter on this, but if I filter on genre it's filtering again. That's a cleaner way to make sure that we're not just taking random user input and sending that on through.
Now the next step in this process is to figure out how to send just one ID. If you remember when we were talking about REST, ideally what we want to do is send slash and an ID number and have that return back an individual book or an individual item, so what we're going to do next is we're going to implement this /books/id and have that return just a single item from our list. The way we're going to do that is by implementing a new route in our router, so we'll do bookRouter.route and this time instead of just /books we're going to do /books/ID, let's do bookId. That makes that a little bit more readable. Okay, now we'll do the same, actually let's just copy and paste that whole thing. Get rid of the query because we're not going to do a query. Now instead of Book.find we're going to do Book.findById and we're going to pass in req.params.bookId. Now this is going to be whatever this is, so if I put just :Id it's going to be req.params.Id. In this case we did bookId to make it a little bit more readable, and so I'll get req.params.bookID. I'm going to get rid of the S's here and that's it. Now we're done implementing that piece. Once we save it our Gulp will restart automatically and let's try this again and see if that worked. There you go. Now I can get a single item by having the Id up here, so if I delete that Id I get my list, and if I want this one I'll just do / and that Id and there's my list.
In this module we're continuing our journey of building out a RESTful API with Node and Express. We've successfully implemented the HTTP Get verb to get both a list of items and a single item. We've wired everything up to MongoDB and we've implemented query string parameters to make sure we're only searching for single items. Now at this point we have a true API that's returning data from a database, but we're not even close to done yet. We still have to be able to put data into our database through the post method, so that's what we'll look at next.