Instructor: So you already learnt
how to create new documents in the database.
But in this lecture I'm going to show you
an easier and even better way of doing so,
as we implement our create tour handler.
So at this point our API
basically doesn't do anything anymore.
It doesn't work anymore
because basically we deleted all the functionality
that we had in the last video.
And we did so, so that over the next couple of lectures
we can rebuild it using a real database.
Okay, so basically finally building our real API.
And we're gonna start by implementing
the createTour function.
But just remember the handler function
that is called as soon as there is a post request
to the tours route.
So that's what we have here in tourRoutes.
So let's put that here.
So what I just said is this.
So we have this checkBody here.
Which actually is something
that we will be able to delete as well.
So where is that, actually?
checkBody
alright, so this is yet another of these functions
that we really don't need anymore.
Because this was basically to validate the body.
So to see if it had the name or the price property in them.
Right?
But now our mongoose model
is actually gonna take care of that.
And so again, this here was nice
to actually show us how middle-ware works
but now we can get rid of it.
Okay, and so I'm gonna delete it from here as well.
Give it a new save.
And it's now back to working.
Anyway the function that we're creating now
is this createTour function.
Where just the one data is going to get called
as soon as someone hits the tour route with a post request.
Okay, so just to recap that
because I know that it can be a bit confusing
with these different files and different folders
and different functions.
But it's also really important
that we start organizing our code
right from the beginning.
Okay?
Anyway, we are here in the createTour function.
And so let's now actually create a new tour.
And we're gonna do that based on the data
that comes in from the body.
Remember that?
Now remember how we used to create documents
a couple of lectures ago.
So we did it like this.
For example let's say newTour
then equal to newTour
and then the data in there.
So we did it like this and then that's a new tour.
And then we type newTour.save
and that works kinda fine.
But we can do it in an even easier way.
So instead of doing this we can do
Tour.create and then paste the data in there.
Okay and that will do the exact same thing.
The main difference is that in this version here
we basically call the method directly on the tour
while in this first version we called the method
on the new document.
Okay, and so that is completely different.
So again we had the tour that we created
from the model.
And then on that tour we used the save method.
Because the document has access to this method
and a lot of other methods as well.
But here in the second situation
we call this create method right on the model itself, okay?
Now remember how this save method here returned a promise.
And so this create here does return a promise as well.
And so in order to get access to the file document
as it was created in the database,
we would then to have used .then okay?
But instead of using promises like this,
I'm gonna start using async await.
Alright.
So this function here should be an async function.
So all we need to do
is to write async right here.
So we have async and so we can now await the result
of this promise here.
So I hope you are familiar with this.
And I actually have a section in this course
that deals with exactly this kind of stuff.
So if you didn't watch that section
but are still not 100% familiar with async await
then please go ahead and watch that section
so that you really understand what's going on here.
Okay, so instead of using this then here
I'm gonna use async await
and then save the result value of this promise
in the new tour variable.
Okay, now the final piece of the puzzle here
is to of course pass some real data into this create method.
And so instead of this empty object
we're gonna pass in the request body
so req.body and so that's the data
that comes with the post request, right?
Now just one more time,
just to make sure that everything is clear to you.
Okay so we can use the tour model directly
and call the create method on it.
Then into that function we pass the data
that we want to store in the database as a new tour.
And that data comes from the post body, right?
And so that's stored inside of request dot body.
So this variable here.
Now this method here will then return a promise.
And we await that promise using async await
and then store that result into the newTour variable
which will be the newly created document
already with the ID and everything, okay?
So I'm gonna keep this code here
just as a reference.
And for now let's get this piece of data here back.
Piece of code actually.
Give it a save.
And now we get this ES lint error.
So let's take a look at that
just put our mouse on here.
And it tells us that async functions are not supported
until this node 7.6
and so this ES lint error comes from that node plugin
that we actually installed.
So you can see that here.
Alright, so what we're gonna to do fix this
is to simple go to package.json
and in here you find the node version
that we are actually using.
So that's very simple.
We just need to specify the engines property
here in our json document.
And set node to greater or equal
than 10.
Okay, and that's because in this course
we are using at least node ten.
So 7.6 would be enough in order to make that error disappear
but of course we specify the real version
that we're actually using.
So we give this one a save.
Close that up.
And so now our error here is actually gone.
Now just one more step before we can actually try this out
in our Postman app.
And that is that we actually need to handle errors.
Okay, and so keep in mind that with async await
we need to test for errors using the try catch syntax.
So we write a try block.
Then wrap all our code in there.
And then finally a catch block.
Which as we already know has access to the error object.
And now what do we actually put here?
Well we need to think about
when exactly an error can happen.
So remember like two lectures ago
when we were creating our first documents.
We got an error back then
when we tried to create a document
without one of the required fields, right?
And so that was a validation error.
And it's one of the errors that would get catched here.
Okay because if we tried to create a document
let's say without one of the required fields
then this promise that is created here
would be rejected, okay?
And so if we have a rejected promise here
then it will enter the catch block.
And so therefore, basically in this catch block here
we want to send back a response
saying that there was an error.
Alright so res.status here again
and 400 which stands for bad request.
.json
and now something very similar to this one
but its status and that's fail
and then instead of data here we send a message
and for now lets just set the message to the error.
Alright.
And let's now finally get back to our Postman application
and give this a try.
Okay, so create this one
and let's now create a new tour.
So right now here we have
the name duration difficulty and price
and so let's actually also add the rating
and that needs to be in double quotes
4.7.
Alright, and now comes the moment.
Send and indeed here we go.
So this is the tour
that we just created.
We have our rating.
We have our name and we have our price.
And of course the automatically created ID.
Now you might notice
that we have no difficulty and no price.
Well why do you think that is?
Well that's because these two fields
are actually not in our schema
and so therefore they are not put in the database.
So everything else that is not in our schema
is simply ignored.
So that is the power of our schema, alright?
Great, now let's actually try to send this again
and so that should give us an error, right?
And indeed there we go.
We have our 400 bad request.
And we have this message
which is the complete error that we got.
And so here we see that the error message is duplicate key.
And so that's because we already have the Test Tour 2.
And so it could not create another one.
So let's just create another one here like Jonas Tour.
It doesn't really matter, okay?
I just wanna create it,
first without any of this
just to see if we get another error.
And indeed we get some more errors here.
This time saying that
that the tour validation failed
because a tour must have a price.
Okay, so you see that right now we have
this kind of weird error structure here.
So Mongo DB gives back this huge complete error object.
And later on we're actually gonna take care of that.
So we will have an entire section on error handling alone.
And by then we will create some more meaningful errors.
Okay, for now let's just replace this error object
with some normal string here.
So let's say invalid data sent.
Okay, so don't do something like this
in a real production application
but again we're gonna have some real error handling
a bit later which is gonna take care of that.
Okay, so displaying meaningful errors to the client.
So let's just go back here
send it again.
And so now we get this normal string here.
So let's just create the price here.
Let's set it to 567
then send it.
And so now you will see
that our default rating here is actually still working.
Let's now figure all of this out in compass as well.
And indeed we get our four tours in the database.
So all these weird tests
that we've been doing up until this point.
So let's just go ahead and delete these last two.
That were really just for testing.
Alright.
So something went wrong here I guess.
Okay, now we're back to these two.
Let's now just create the third one
that we actually had before in the last section.
Which is the Snow Adventurer.
So the Snow
Adventurer.
The price was ...
I'm not sure anymore
like 697 maybe.
And the rating is like six
or actually 4.8.
Sent that guy.
And so indeed here we go.
Great.
Just to quickly recap our createTour function.
So we have a try catch here
because we're actually using an async await function here.
Right, so we use async await
because this tour.create returns a promise
that we're awaiting so that we can then store
the newly created tour document
inside of this variable
and then send it along with the response
to the client down here.
Okay but in case there is an error,
like a validation error for example
then that error is gonna be catched
and we send something else back to the client
with this error message.
So this is how we create documents using mongoose.
Next up we're gonna talk about reading documents.