Enforce Schemas in MongoDB using Mongoose Models

Share this video with your friends

Send Tweet
Published 2 years ago
Updated a year ago

One of the great things about NoSQL databases is that you do not have to decide on your data schema while developing. As you get closer to production though, you'll often want to more clearly define the shape of the data you are working with.

Kevin Cunningham: [0:00] I have a simple form that takes a JSON user object and posts it to my MongoDB Instance, and returns the response I get from there. The response includes how many results were committed and which fields, the name and the id.

[0:20] As in NoSQL database, this can accept data in any form that's sent to it, with any type. Our API de-structures the MongoClient from the mongodb library, gets a user object from the request body and returns an error if no user object is sent.

[0:41] Otherwise, it connects to Mongo using url, defines our database object on our collection as users, and then insert our user returning the response to the client.

[0:57] Restrict the structure of the data that's accepted and processed by MongoDB. We can use the model's functionality provided by the Mongoose package.

[1:06] First, we'll install the package by using npm install mongoose or yarn if you prefer. Then we'll create a new file at models/user.js, where we'll create our user model. Inside our new file, we'll import the Mongoose package that we've just installed.

[1:24] Then, we will use the same connection url on connect using Mongoose. We need to pass some options to the connect function, including useNewUrlParser because MongoDB updated their API and used UnifiedTopology. If you forget either of these, you'll be reminded in the console.

[1:44] After we have connected, we'll log out DB server connect. Otherwise, we'll log the error.

[1:53] Next, we'll destructure the schema from the Mongoose library and then define our user schema. In this instance, we're using three strings, one for name, one for email, and one for avatarUrl. There's a lot of data types we could use here, full details are found in the documentation.

[2:10] Next, we'll try to see if there is a Mongoose model called user already. If not, we'll create it using our user schema. Finally, export our user's model.

[2:22] We don't need to update our API to use our new functionality or remove the original MongoDB client. Instead, we'll import the user from our models/user.js file. I'm going to rename the user to incomingUser to try to reduce some confusion and return an error if there is no incoming user.

[2:44] I need to completely change this logic. Now I'm going to say my newUser is an instance of the user that we've created based on the incomingUser that we have just received.

[2:56] We'll then await newUser with the save function that exists on the model. The save function accepts a callback function which will use the error and the user.

[3:06] If there is an error, we'll log it to the console. Otherwise, let's respond to the client with a success message, and the user response we receive from MongoDB.

[3:17] If we go back to our form, it works just as before, except now, if we pass in any odd data in our JSON object, it might be sent to the server, but it won't be persisted to the database. Only those fails which we've set up in our schema will be accepted and persisted.