‫So now that you know the basics
‫of Mongoose by implementing
‫all the four correct operations,
‫it's now to finally matter our tour data a bit better
‫in order to make the tours more complete.
‫So at this point, our tour documents can only have a name,
‫a rating, and a price.
‫But of course, we need so much more data here,
‫because the goal is to have a very data-rich API,
‫like this one.
‫So let's take a look at the final version
‫actually here as a reference.
‫And so that's this one here.
‫And so we get all tours,
‫and it's gonna look a bit like this.
‫Okay, so you see that on each tour,
‫we have a start location, we have ratings average,
‫ratings quantity, images, start dates.
‫Guides, name, duration, maximum group size,
‫difficulty, price, summary,
‫description, image cover, locations.
‫Even a slug, reviews, duration in weeks, and the ID.
‫So you see a lot of data,
‫and we're not gonna add all of the data
‫in this lecture here.
‫There are some pieces that we cannot add as of yet,
‫but we can of course make it a bit more complete, okay?
‫And let's actually save this here, like as a reference,
‫and get all tours, and I'm gonna put it outside
‫of any folder.
‫So let's put it just here at the top.
‫And that doesn't work for some reason.
‫Okay, let's just put it here, then.
‫Okay, let's get,
‫that's correct.
‫And so again, I'm leaving it here,
‫in order to keep comparing what we have
‫with what we're aiming for.
‫So anyway, let's go back,
‫and start with what we have already,
‫and we have the name.
‫And so that's already good enough,
‫so for now I'm gonna leave it like this.
‫So the name, then we also want a duration.
‫And that duration is a number, and it is required.
‫So set it to true, and then the message is,
‫a tour must have a duration.
‫So these required validators here basically
‫are the only validators that I'm gonna add
‫to each of these fields here for now.
‫Later on, when we're going to talk more in detail
‫about validators, we're gonna add a lot more.
‫But again, for now, I just want to make
‫some of these fields, not all of them, required.
‫Next up, we have the group size.
‫So basically, how many people can at most
‫take part of one tour.
‫And so I call that one the maxGroupSize.
‫And so that again should be a number,
‫and it is again required.
‫Tour must have a group size.
‫Don't forget the comma here.
‫Next up, we also need a difficulty.
‫And this one is a string, and later on,
‫we will define that it should be either medium,
‫easy, or difficult, but again,
‫that is actually a validator,
‫and I'm gonna leave that for a later time.
‫Okay, for now, I'm just saying
‫that it should have a difficulty.
‫Next up, let's talk about the ratings.
‫So right now we have a field called Rating,
‫but in fact we want to have one field
‫for the rating average,
‫and one field for the ratings quantity.
‫So basically the amount of ratings that there are.
‫So later, there will be another resource called reviews,
‫where users will be able to write reviews
‫about tours and give ratings.
‫And that's gonna be a completely different resource,
‫and a completely different model.
‫But still, we want to have basically a summary
‫of these ratings and of these reviews here in the tours.
‫Alright, and the reasons for that you will learn a bit later
‫once we start how and why we model data in NoSQL databases,
‫and specifically in MongoDB.
‫Okay, for now, let's just add the ratings average,
‫and the ratings quantity.
‫Okay, so we leave this here as number,
‫and with this default,
‫and the ratings quantity, ratingsQuantity.
‫That should of course also be a number,
‫and the default will be zero.
‫Because of course, in the beginning,
‫there will be absolutely no reviews, when the tour is new.
‫Now I didn't give these two properties here
‫a required value, because it's not the user
‫who creates these tours
‫who will actually specify these values, right?
‫So when we create a new tour,
‫we will never specify the ratingsAverage,
‫neither the ratingsQuantity,
‫because that will later on be calculated
‫from the real reviews, okay?
‫Next up, we have the price here,
‫so that's fine like this,
‫and we might also have a discount.
‫So let's say that this company,
‫so Natours, wants to give a discount to one of the tours
‫at some point, and so they can specify
‫a discount price here as well.
‫So priceDiscount, and so let's just put it here at number.
‫We don't need any schema type options here.
‫For example, it's not required,
‫and so for now, let's just leave it like this.
‫Next up, we can specify a summary of the tour.
‫So the summary is of type String.
‫But I will not actually make it required.
‫Okay, and that's simply because it's not
‫on the front page of our website.
‫Okay, so basically it's not on the overview.
‫And I'm gonna show you that in a second,
‫but for now let me just add here
‫another schema type option that I didn't show you yet,
‫which is called trim.
‫And trim only works for strings.
‫And I will set it to true.
‫So remember how I said that there are different schema types
‫for different types here,
‫and so for string, we have a schema type which is trim
‫which will remove all the white space
‫in the beginning and in the end of the string.
‫Okay, and so if someone enters, for example,
‫this tour, blah blah blah, doesn't matter.
‫So if someone enters this,
‫then all this whitespace in the end
‫and in the beginning here will get cut.
‫And actually, we can put the same thing on the name,
‫for example, here.
‫Okay, why not?
‫So let's leave it like this.
‫Here I see that it's actually called duration,
‫not durations.
‫Alright, so that's the summary, which is also misspelled.
‫So summary like this.
‫Oh, and yeah, now I wanted to show you
‫the Natours website, actually.
‫So that's back to our Mongoose documentation.
‫But this is what I want to show you.
‫So Natours.dev, which is the original of this application,
‫and so this is the data that we have in our API,
‫and that we also of course need in the database.
‫So we have all this data.
‫So this tour name, we have the difficulty,
‫we have the duration, we have,
‫this is a summary, then we have a start location,
‫we have the amount of locations,
‫we have a start date,
‫we have the maximum group size in here,
‫and we have to price, the rating average,
‫the rating quantity.
‫We also have an image here.
‫And then here on the details page is where we have,
‫we have the summary down here.
‫We have the guides that I just showed you in Postman before.
‫We have some more images.
‫We have here all the locations,
‫and we have all the reviews.
‫Okay, so as I was telling you,
‫not all the data is on the Overview page,
‫and so not all the data is also required.
‫Okay, so let's move back here.
‫Next up, I want to add a description.
‫And this is a type of String,
‫and let's set trim to true again.
‫And I just remembered that the summary
‫is actually on the Overview page.
‫And so let's make this one required.
‫So you add here at the end,
‫true,
‫a tour must have a description.
‫Okay, next up, we will specify the imageCover.
‫And so that's the images that you see on the overview page
‫and so let's set this one actually to require this role.
‫So the type should be string,
‫because basically this will simply be the name
‫of the image here, which then later,
‫we will be able to read from the file system.
‫Okay, so really just the name of the image.
‫So basically a reference will be stored in the database.
‫And that's a very common practice, okay?
‫So we could store the entire image as well in a database,
‫but that's usually not a good idea.
‫We simply leave the images somewhere in the file system
‫and then put the name of the image itself
‫in the database as a field.
‫So set it to required, true,
‫a tour must have a cover image.
‫Nice, next one is the rest of the images.
‫And now here, we have something new, okay?
‫Because we have multiple images,
‫and I want to save those images as an array.
‫And actually, as an array of strings.
‫And so the way to do it is to simplify specify here
‫an array of strings, just like this.
‫So I want it still to be of type string,
‫but I want it to be an array.
‫So an array in which we have a number of strings.
‫And so that's how I can define this, okay?
‫And we will use this later for something else again.
‫And so we will then actually pass in
‫more schema type options than just a type,
‫and so by then we will use that again, alright?
‫For now, though, let's move on,
‫and the next field that I wanted to add here
‫is the createdAt.
‫And the createdAt field should basically be a timestamp
‫that is set by the time that the user gets a new tour.
‫So this here should of course be added automatically.
‫Again, at the time the tour is created.
‫So how do we do that?
‫Well first of all, we set the type to Date.
‫So Data is yet another JavaScript built-in datatype,
‫and so we can use that here.
‫Okay, so the type is Date,
‫and then we simply need to set a default,
‫and the default is the JavaScript
‫built-in function Date.now.
‫And I'm sure you are familiar with this one.
‫So this will simply give us a timestamp in milliseconds,
‫which basically represents the current millisecond.
‫Alright, now in Mongo,
‫this is now immediately converted to today's date
‫in order to make more sense of this data, okay?
‫So yeah, that's the automatically created timestamp.
‫And now finally, we need to also pass in an array of dates.
‫And now finally, to finish for now,
‫we also want to able to define an array of start dates.
‫So startDates, and again, we simply define an array,
‫and then say that in there we want dates.
‫Alright, so these startDates are basically different dates
‫at which a tour starts.
‫For example, we can have a tour starting
‫in December this year,
‫and then in February, the next year,
‫and then another one in the summer,
‫and so different dates for the same tour
‫are simply different, let's say,
‫instances of the tour starting on different dates.
‫Alright, I hope that makes sense.
‫Anyway, this one here will not be automatically created
‫by MongoDB, and MongoDB will then automatically
‫try to parse the string that we passed in as the date
‫into a real JavaScript date.
‫For example, we could pass in something like
‫let's say 2021, March 21st,
‫and again Mongo would then automatically parse
‫this as a date.
‫You can also specify the date.
‫For example, saying 11 and 32 minutes, alright.
‫Or we could also simply input a Unix timestamp,
‫so a timestamp like in this format here.
‫Okay, and so all of these formats,
‫basically, Mongo will try to parse them into a date.
‫And only if it can't, it will then throw an error.
‫(exhales) So this was a lot of work.
‫Let's give it a save here.
‫And the way that we can then try this out
‫is to go here to our dev-data,
‫where we have this tour-simple.json file,
‫which is the one we've been using in a previous section.
‫All right.
‫And so all I'm gonna do here
‫is to just grab all this data here,
‫and then use that one to create a new request, okay?
‫So we want to create a new POST request here,
‫and with all that data,
‫instead of having to write it out manually.
‫Okay, so pasting all of this here.
‫And now indeed, we do not need the ID.
‫So we needed it before,
‫when we were doing our file-based API,
‫but that's over now, so let's get rid of that.
‫And so all the rest of the data
‫that we marked that's required is now actually here,
‫and even some more.
‫So let's try to see what happens when we submit this.
‫And now we get invalid data sent.
‫So let's actually go to our tour controller,
‫and in here, where we create a tour,
‫instead of this message let's actually go back
‫like we had it before and send the entire error
‫just so we see what is actually going wrong.
‫So send it here, okay, and the problem was
‫that we have The Snow Adventure already defined.
‫So let's first get rid of that.
‫Yeah, so here we have The Snow Adventure,
‫so we should delete this, and for that,
‫I'm using our own API,
‫so we can already put it to some use here.
‫So that one should now be gone,
‫and so now we should be able to add this as a new tour.
‫And indeed, it's now here.
‫So here is all the data that we just specified
‫in this nice format.
‫So what is interesting now is to actually see
‫the createdAt timestamp.
‫So that's the exact time at which I'm recording this video.
‫And so this one was of course automatically created
‫by this piece of code that we have somewhere here.
‫Yeah, this.
‫So that date is coming from this Date.now timestamp
‫that JavaScript then automatically parses
‫to this nice and readable date.
‫Then here we have these arrays.
‫Okay, so this array and another array,
‫and of course, the automatically generated ID, alright?
‫So if we come here now,
‫we then have of course three tours.
‫First, the other ones which are not so complete,
‫and then all of these.
‫Now what's interesting to see here is that Mongo
‫also actually updated kind of the tours that we already had.
‫So for example, we had rating here,
‫but now that our schema completely changed,
‫it then added this ratings average,
‫and also this ratings quantity, both to their defaults,
‫and the same actually here.
‫It also created this timestamp.
‫It created, yeah, it created images and start dates,
‫with these empty arrays.
‫And so it kind of changed all this data here.
‫Alright, and so before we start moving on in a project,
‫we should probably go ahead
‫and delete all of this data here.
‫And actually, what we're gonna do in the next video,
‫now that our model is finally completed,
‫at least for this section,
‫we will go ahead and write a small script
‫which will automatically import all of the tours
‫from this JSON data.
‫Okay, so from this JSON file, actually.
‫So it will basically read the file,
‫get all the tours, and import them into the database.
‫Alright, so that's what we're gonna do next,
‫because that will be hugely useful
‫in this section and also in the future.