
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 Models in our application let us know how our data is going to look like.
00:00:06 So let's define it right here in the root of our application by creating a new folder and let's call it models.
00:00:14 And to keep everything organized, we'll create multiple files such as user.model.js as well as a subscription.model.js.
00:00:26 I think you can already start seeing the practice we have.
00:00:29 We create separate routes, separate models, and soon enough, separate controllers for every one of these parts of our API.
00:00:38 Once you understand the gist of it, you'll know how it all works.
00:00:41 So, let me show you how to create that model.
00:00:44 We can first import mongoose coming from mongoose, and then we can define a user schema.
00:00:52 const user schema is equal to new mongoose.schema, to which you can pass an object that allows you to define how a specific model is going to look like.
00:01:04 We can give each user a name, and then we get an object to define more information about that name.
00:01:10 For example, it'll be of a type string, and alongside required, we'll also pass an array and say true, but we can also define an error message if it's
00:01:22 not there, by saying something like username is required.
00:01:26 That way, if something goes wrong in the code, we'll know why it is wrong.
00:01:30 because we're missing a username.
00:01:32 We can also trim it by saying trim true if we have some empty spaces in there and we can give it a min length of something like two characters and a max
00:01:42 length of about 50. What else does the user need?
00:01:45 Well, we can have an email right here and it'll be very similar with a type of string required to true user email is required Unique in this case will
00:01:56 be set to true, because only one user can have that specific email.
00:02:01 With a trim to true, we can also make lowercase to be true as well, because email tend to be lowercase.
00:02:08 And bear with me, I'll also show you how to write a very quick regular expression to check for emails.
00:02:15 We can say that this specific parameter has to match the following format.
00:02:21 As you can see, my copilot wrote it for me here.
00:02:24 Nobody writes regular expressions by hand today.
00:02:27 It's just a forward slash, backward slash, S plus, at sign, backwards, S plus, whatever it is.
00:02:33 Basically, it means that we'll start with a string.
00:02:38 followed by an at sign, some more string signs for the domain, followed by a dot, and then some more characters for the domain name extension.
00:02:46 Something like contact.jsmastery.pro.
00:02:50 Great.
00:02:51 And finally, a user also has to, of course, have a password, which will be of a type string.
00:02:57 Required will be set to true, and will say that the user password is required.
00:03:03 We won't be trimming or messing with the password in any way.
00:03:06 but I will set a min length to about six characters.
00:03:09 Finally, we'll go a bit down, not below the password, but outside of the schema definition, and I'll set timestamps to true,
00:03:18 which means that alongside these properties, we'll also have created ad and updated ad fields, so we know when that user has been created or modified.
00:03:27 Perfect.
00:03:28 With that in mind, we can create a new model off of that schema.
00:03:32 By saying const user is equal to mongoose.model with the name of user, and then we pass over the user schema we want to create that model off of.
00:03:43 Models typically start with a capital letter.
00:03:46 And don't forget to export default.model.
00:03:49 Off of which we'll then be able to create instances of that model, such as different users.
00:03:55 So we can have a user that's going to look something like this.
00:03:58 It'll of course have a name of John Doe, email, I guess of Johnny at.
00:04:07 email.com and finally a password of password.
00:04:11 We'll get to there by using the user.create method.
00:04:16 We'll get to there by doing something like user.create and then passing over the information.
00:04:24 But more on that later.
00:04:25 For now, it's important that we have this model.
00:04:28 Now that we know the basis of creating MongoDB models, let's create one for the subscription, just to recap.
00:04:34 Our subscription will have a bit more fields, as it's the primary part of our application, the main model, schema, and document.
00:04:43 So let's import mongoose from mongoose, and let's define our schema by saying cons-subscription-schema is equal to new mongoose schema.
00:04:55 I'll also immediately add the timestamps is true at the bottom.
00:04:59 And now we can give it all sorts of different fields.
00:05:03 I'll start by giving it a name, which will be of a type string.
00:05:08 Required will be set to true.
00:05:11 And I'll say subscription name is required.
00:05:15 I'll also trim it.
00:05:18 and I'll give it a min length of about 2, and a max length of about 100. After the subscription name, which can be something like Netflix,
00:05:28 we'll have to have a price of that subscription.
00:05:31 This one will be of a type is number, and it'll also have a required property to true, set to subscription price is required.
00:05:40 with a min value of zero.
00:05:43 And we can also add kind of like a message, price must be greater than zero.
00:05:49 After that, we can define the currency that it is in.
00:05:52 This is totally optional because you might be using just a single currency, but in case you want to add it, you can make it of a type string.
00:06:00 But then a cool thing is that you can define it as an enum of one of these properties.
00:06:06 like USD, euros, British pounds, or so on.
00:06:10 You can add your currency right here.
00:06:12 And then, when trying to create a new subscription, it'll ask you for the currency as well.
00:06:17 I'll make it default to USD.
00:06:20 Another very important part of our subscription is the frequency.
00:06:24 How often are you getting charged for that subscription?
00:06:28 And this will be of a type string, and this will be an enum of daily, weekly, monthly, or yearly.
00:06:36 We can also have a category for that subscription, just so we know where we're spending the most.
00:06:43 And it'll be of a type is string.
00:06:48 And we can also make it an enum of something like sports, news, entertainment, lifestyle, technology, finance, whatever it is,
00:06:56 right?
00:06:57 You get the idea.
00:06:59 And they'll make this one required.
00:07:03 set to true.
00:07:03 Let's also define a payment method, which will be of a type string required to true and trimmed to true as well.
00:07:12 And let's define a status of that subscription, which will be of a type string.
00:07:17 It'll be an enum of either active or canceled or expired.
00:07:26 And the default will be set to active.
00:07:30 Now that we have all of these base properties, we also might want to know when is the start date of that subscription.
00:07:37 So I'll say start date will be of a type date.
00:07:41 It'll be set to required to true.
00:07:44 And we can also validate it.
00:07:46 by saying validate to which you can pass an object where you can define a validator function.
00:07:54 So that'll look something like this.
00:07:56 You can define a new callback function where you get the value.
00:08:00 And then you can check if value is lower than or equal to new date, which is basically the current date.
00:08:07 And if that is the case, you can provide a message, something like start date must be in the past.
00:08:14 because you cannot create subscriptions in the future.
00:08:16 And we can duplicate this entire start date, but this time I'll call it renewal date.
00:08:23 Type of date required to true and we'll validate it, but I'll switch it around.
00:08:28 The value must be greater than the start date.
00:08:32 And a pretty cool thing is we're not comparing it with the date.now, we're comparing it with this.startDate.
00:08:40 This, of course, referring to our model.
00:08:43 And I'm not sure whether arrow functions will work with this.
00:08:47 We might actually need to wrap it in an actual function.
00:08:51 So we can say validator is a function.
00:08:54 No arrow signs right here.
00:08:55 Rather, it's a good old function where you open up a function block and then you can return this value.
00:09:03 Perfect.
00:09:04 And we can say something along the lines of renewal date must be after the start date.
00:09:10 And the last missing piece of the puzzle is the user that actually subscribed to that subscription.
00:09:17 So we can say user, and it'll be of a type mongoose.schema.types.objectid.
00:09:27 So we're actually accepting the ID, which is going to be a reference to the user model that we have already created right here.
00:09:36 We only need to get its ID.
00:09:37 Required will be set to true, and we'll also set index to true, which will optimize the queries by indexing the user field.
00:09:46 Don't get me wrong.
00:09:47 If this is your first API that you're creating, well, this definitely is a larger model.
00:09:51 It has a lot of interesting stuff right here.
00:09:53 from strings to numbers to enums, some with default values, others with required values, and even some more specific properties where we're trying to validate
00:10:05 the value that's being passed in by using the validator function.
00:10:08 We're not keeping it super simple.
00:10:10 I gotta keep you on your toes so you're always learning something.
00:10:13 And then we also have references pointing to other models in the database.
00:10:16 Now we'll improve it just a tiny bit more by creating a function that'll happen before each one of the documents is created.
00:10:25 It looks something like this.
00:10:27 Subscription schema dot pre.
00:10:32 And we'll run it pre-save.
00:10:35 So this next function, where you get the next as an argument, will be called before we save that document.
00:10:41 Oh, and we're using the function keyword right here, so we don't need the arrow sign.
00:10:47 What this function will do is it'll auto calculate the renewal date if missing.
00:10:55 So if we don't provide the renewal date, therefore we don't have to make it required, it should auto-calculate it based on the start date and the renewal period.
00:11:05 So we can say if no, this.renewalDate.
00:11:09 In that case, we can define different renewal periods like const renewal periods is equal to an object.
00:11:18 where daily will be set to 1, week 7, monthly to 30, and yearly to 365. Then we can set up the renewal date to look something like this.
00:11:28 This.renewalDate is equal to newDate from startDate.
00:11:32 So now we have just made it a startDate, but now we have to actually increase it by saying this.renewalDate.setDate, it'll be equal to this.renewalDate.getDate,
00:11:47 plus renewal period of this dot frequency.
00:11:51 Might be a bit confusing, but basically what we're doing is we're adding this number of days based on the frequency that we pass in.
00:11:59 So for example, if we started it on January 1st, and the frequency is something like monthly, in that case, it'll be 30 days,
00:12:10 which will end up being January 31st.
00:12:13 Make sense?
00:12:15 Hopefully so.
00:12:16 We can go outside of this if, and we can also auto-update the status if renewalDate has passed.
00:12:24 So that'll look something like this.
00:12:26 If this.renewalDate is lower than newDate, which is the current date, then we simply set the this.status to expired.
00:12:35 After we do everything, we can simply call next and make it proceed with the creation of that document in the database.
00:12:42 So in this case, you not only learn how to create a model that has all sorts of different properties, you also learn how to validate those properties before
00:12:51 they're entered, and you learn how you can call specific actions before a document is saved, perform additional logic, and then modify,
00:13:01 delete, or update properties on that instance based on external criteria, the lack of some properties like the renewal date,
00:13:09 and so on.
00:13:11 Perfect.
00:13:11 Finally, let's create a model out of that schema and let's export it.
00:13:17 With that, we're done with the two primary models, the user model and the subscription model.
00:13:22 And as soon as we authenticate our user, we'll be able to put it to the test where we'll be able to attach different subscriptions to different users.
00:13:31 Before we do that though, let's improve the global error handling of our application.
00:13:35 because as it's growing, we might start to make some mistakes in our code.
00:13:39 So it's nice to have a centralized error handling system to track all of those errors.