Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
To serve the API we have to do one final thing: connect incoming requests to the database.
-
0:00
[MUSIC]
-
0:04
We have one final thing today, connect incoming requests to the database.
-
0:10
This will take place inside the route handlers.
-
0:13
The handlers will receive the requests from the outside world and
-
0:16
to use Mongoose to persist or retrieve the data.
-
0:19
Let's connect Mongoose to the route handlers and response to requests.
-
0:24
In the routes file, let's start by importing our question model.
-
0:31
We'll require it at the top and assign it to question.
-
0:50
Now we'll be able to use question to create documents and query the database.
-
0:55
We can start with the root routes get request handler.
-
1:01
For this, we want the API to return all question documents.
-
1:06
On the question model, we can call the find method,
-
1:12
and pass in an empty object literal followed by a callback function.
-
1:34
To make sure the question objects are sorted so
-
1:37
that the most recent ones come first,
-
1:39
we need to add additional parameters to find the method before the callback.
-
1:45
If the second parameter is not a function,
-
1:48
in other words our callback function, the find method expects it to be
-
1:53
what Mongo calls a projection to limit the fields returned by the query.
-
1:59
In other words, a projection is a way to return excerpts of a document.
-
2:04
Since we don't want partial documents, we want full documents,
-
2:09
we'll pass in null as the second parameter.
-
2:14
And then we can specify how we'd like our ordered results as the third parameter.
-
2:21
Passing in an object literal.
-
2:30
By entering the property of sort, we can specify another
-
2:35
object literal with the key we want it to be sorted by.
-
2:41
Entering -1 means the documents will be sorted in descending order.
-
2:47
This means the most recent data will be at the beginning of our results array.
-
2:53
Without this null placeholder, Mongoose would try to
-
2:57
use this object as a projection.
-
3:03
So we need this null value here.
-
3:05
This tells mongoose how to sort our results.
-
3:11
The callback is now our fourth parameter.
-
3:15
In the body of a callback function
-
3:18
we first want to handle any errors that may result from executing this query.
-
3:23
So we'll need to access the next function and
-
3:26
hand it off to express's error handler.
-
3:47
If there are no errors, we can send the results to the client's request.
-
4:02
Because we're getting JavaScript objects back from Mongo, we can
-
4:06
drop them straight into the JSON method on the response object and send them out.
-
4:11
I want to show you a slightly different way to query the database with Mongoose.
-
4:16
One but you might find a little easier to use
-
4:19
than this full parameter method signature.
-
4:22
If we don't pass in a callback function to the find method,
-
4:25
it doesn't execute the query immediately but rather returns a query builder.
-
4:31
You can use this builder to modify the query with additional methods.
-
4:36
When you're ready to execute the query,
-
4:38
we can call the exec method on the builder and pass in the callback function into it.
-
4:43
So first, we'll call find with an empty object literal
-
4:49
as we did before to get all the results, then call sort on it.
-
5:08
And passing in that same sourcing object that we used before.
-
5:13
At this point the query hasn't been executed yet,
-
5:17
the sort method returns another query builder so
-
5:20
you can chain any number of modifications together through additional method calls.
-
5:27
This is the only one we'll need, so we can call the exec,.
-
5:36
And pass in our callback function.
-
5:46
This executes the query and calls the callback function.
-
5:51
If you'd like to read more about this style of building queries,
-
5:55
there is a link in the documentation in the teacher's notes.
-
5:59
The style you choose is up to you.
-
6:03
Now let's handle the post action for this route.
-
6:06
To create a new question document from the incoming JSON on the request body,
-
6:11
we can pass it in directly to the model constructor.
-
6:35
Then we can call save on it.
-
6:39
And pass in a callback function.
-
6:51
Don't forget that add in next, as this will help with errors.
-
7:10
We can use an HTTP status of 201 to indicate to the client that
-
7:14
the document was saved successfully.
-
7:24
Finally the document can be returned as JSON to the client.
-
7:46
The next handler to complete is the get request for a single question.
-
7:52
For this we can use the findById query method on the model,
-
8:00
passing in the questions ID from the URL.
-
8:15
Let's pass in a callback, With an error and the document.
-
8:26
Let's handle the error like we did before.
-
8:33
And return the question document to the client as JSON.
-
8:52
Now this is a fine way to do it but there is a better way.
-
8:56
Express allows us to trigger a handler whenever a URL parameter is present.
-
9:02
In this case, if qID exists, we can preload
-
9:08
the question document in the handler so it will be present on any matching route.
-
9:14
To do this, let's go to the top of our router file.
-
9:19
And on the router object, Call the param method.
-
9:29
The param method takes two parameters,
-
9:32
the name of the route parameter as a string, and a callback function.
-
9:44
This callback will get executed when qID is present.
-
9:57
The callback takes the same parameters as other middleware.
-
10:01
Except for the last one which takes a value from the route parameter,
-
10:07
in this case qID.
-
10:17
So first we can load the question document and if there's an error,
-
10:22
it will pass it forward to the error handler.
-
10:31
If the document can't be found,
-
10:34
we want to return a follow for 404 error to the client
-
10:49
Remember to set the status property on the error
-
10:54
object since the error handler will look for
-
10:59
that and use it if it's there.
-
11:08
Finally, if it exists, let's set it on the request object, so
-
11:13
it can be used in other middleware and route handlers that receive this request.
-
11:26
Finally, let's call next to trigger the next middleware.
-
11:39
Now, we can go back to the route handler we just made, and simplify it.
-
11:45
We won't need to query the database anymore because the param handler will be
-
11:49
doing that, so we can delete that.
-
11:52
And we don't need to handle the errors since the param handler is doing that too.
-
11:59
All we really need to do now is send out the document to the client.
-
12:17
Now we're ready to tackle the answers collection route.
-
12:21
Since we're already having the question loaded by the param method, we can
-
12:26
start to see here how it's relieving us from typing a query for each route.
-
12:31
It's just there in the request.
-
12:38
After getting the reference to the pre-loaded question and
-
12:41
accessing the collection of answers We
-
12:46
can simply push the object literal version of the document we want to add.
-
13:07
Mongoose will create the document for us.
-
13:10
To save it, we need to call save on the question document.
-
13:21
And in the callback,
-
13:33
We can set the http status to 201, which tells the client that their resource
-
13:39
was successfully created, and then send the response back to the client.
-
14:00
But the specific answer route, we can say that another
-
14:04
parameter handler would be useful here to preload answer documents.
-
14:10
Let's go ahead and make that now.
-
14:28
Under the parameter handler for qID, we can create a similar handler for
-
14:34
the answers using the aID parameter.
-
14:45
Mongoose has a special method on sub documents array called ID.
-
15:02
The ID method takes an ID of a sub-document, and
-
15:05
returns the sub-document with that matching ID.
-
15:22
If the answer can't be found, We want to send a 404 error.
-
15:36
Otherwise, we'll call next to pass control back to the router.
-
15:56
Now that the answer is loaded, let's use it in our put route,
-
16:00
we can use the update instance method.
-
16:15
Remember, we'll pass in an updates objectm which will contain the properties and
-
16:21
values we want to modify on our existing document.
-
16:25
In this case, it's the requests body.
-
16:36
Then a callback to fire, after saving the updates to the database.
-
16:56
We'll just send the results in question document back to the client.
-
17:12
The next route is the one that deletes answers.
-
17:25
Mongoose documents have a remove method.
-
17:30
We can use the remove method on our answer.
-
17:39
Then in the callback, we'll save the parent question.
-
18:16
This will take another callback where we can send the resulting
-
18:20
question back to the client.
-
18:31
Finally let's complete the vote route.
-
18:34
First, let's add a line to the validator
-
18:37
to make everything a little more coherent and readable.
-
18:51
Now we're putting the vote string directly on the object.
-
18:55
It allows the reader to quickly understand what the value of the variable is about
-
18:59
when they read it in the next callback function here.
-
19:09
This is opposed to rec.params.dir, which probably wouldn't
-
19:14
help them understand it's holding the vote direction up or down.
-
19:19
Now let's call our instance method vote on the answer, passing in the vote string and
-
19:25
then a callback with a response back to the client.
-
20:14
And don't forget to include the next in your handler.
-
20:20
See how clean the instance method makes it easier to apply the vote to the answer?
-
20:25
Nice work.
-
20:26
This step completes our API.
-
20:30
We now have an express server that receives restful requests,
-
20:34
communicates with the database, and sends responses back to clients.
-
20:38
Great job.
You need to sign up for Treehouse in order to download course files.
Sign up