Building a Model - AdarshMaurya/mongodb-and-mogoose-for-node-getting-started GitHub Wiki

Introduction

Welcome to this module on building a Mongoose model. In this module, we will take what was learned about laying out a Mongoose schema in the previous module and build our first model based on that schema. We will then discuss Mongoose documents and subdocuments and the relationship between these documents and MongoDB documents within a collection. In the demo, we will build out our standup meeting notes model, construct a document from that model, and save it to MongoDB.

Our First Model

To illustrate building out our first model, let's start with one of the simple schema examples we looked at earlier, the customerSchema. To build a Mongoose model from the schema, which is named customerSchema in this example, we simply need to pass into the mongoose.model method the name of the model and the schema we wish to build this model from. A third optional argument not shown here would specify the MongoDB collection name that you want your document instance of this model to be saved in. Since I have not supplied that here, Mongoose will provide a collection name from the model name given. Mongoose will attempt to pluralize the model name, so we may end up with Customers with an S rather than Customer for our collection name. If that's not the desired result or if the collection name already exists and perhaps you need to match that name, simply provide that third collection name argument, and you should be good to go. Keep in mind that you can build out any number of models against the schema definition, and as shown here, we can append on additional key-value pairs to our schema to customize it even further. Here, we've taken our base schema and added on a discount code and then built a discounted customer model from that appended schema definition. Now let's take a look at where we left things off with our standup notes schema and what it would take to export a model from our standup.js file. As with the previous example, we're simply going to pass into the mongoose.model method two arguments. The first being what we want to name our model, standup in this case, and the second, the previously defined schema, standupSchema. The difference here is that we are not assigning this model to a variable, but rather exporting it, or if you will, exposing it or making it available to other files that may require or include this module. We'll see that in action here shortly in the demo.

Documents

As mentioned in the introduction, we're now going to discuss Mongoose documents and how they are constructed and the relationship to MongoDB documents. A Mongoose document is a direct representation of the document saved in a MongoDB collection. That's a good thing for us actually because it eliminates the need for some type of object relational mapping between mismatched systems. Mongoose is really more of an object document modeling tool than a mapper. We've already learned that everything in Mongoose starts with a schema and that a model is built, or maybe we can say compiled, for my schema. So now let's talk in a little more detail about documents. A document in Mongoose is simply an instance of our model. In the code example shown here, we have a really simple schema named personSchema with first and lastName properties. Next, we build a Mongoose model from the personSchema, which is shown here as the second argument to the model method. Again, the first argument is simply the name we wish to give our model. We've seen this much in the previous example, so let's continue on with the code example. Here, we've created a single instance of our model and named this new document zevia and then supplied values to the firstName and lastName properties. Later, we'll see how to save and retrieve documents such as this to and from MongoDB through Mongoose.

Sub-documents

Now let's talk about Mongoose subdocuments. This would be a good time to revisit the quiz schema example we looked at earlier in the course.

Demo: Saving Documents

Now that you've learned about building a Mongoose model from the schema and that documents and subdocuments are instances of the model, it's now time to open Visual Studio Code back up and develop the code to save a Mongoose document to MongoDB. We'll start by building each model from its respective schema. Once that is done, we'll develop the code used to save the Mongoose document to MongoDB. This will be done in our Express API, and we'll test that using Postman. Let's get started on that now. Back in Visual Studio Code, and to start, we'll open the standup.js file. All we need to do to obtain a Mongoose model from the schema is to add this line of code, model.exports = mongoose.model, and the first property here is the name of the model, we'll name this one Standup, and the second property is where we pass in the schema this model is based off of, in this case, standupSchema as defined above. Save this file, and we'll do the same thing for the two remaining files. Project.js, adding in module.exports = mongoose.model, name this one project, and pass in projectSchema. And teamMember.js also adding in module.exports = mongoose.model with a name of TeamMember and passing in teamMemberSchema. That was pretty easy, and we now have Mongoose models available for us to use, but where will we use these models at? Let's go back to the API routes we stubbed in earlier in the course and develop each of those out a little more now. Starting with the standup route, we only have the GET route stubbed in right now, but since we're wanting to save a Mongoose document, we'll need a POST route here now. Router.post with the path of /standup and a callback function with two properties, request and response. Now on the body of this function is where we start to make use of the Mongoose model we just finished. Let note = new Standup and pass in the request body, which will be a JSON object. We need to go back to the top of this file and add a reference to this standup model, const Standup = require and move back a couple folders, models/standup. Back in the callback function, note here is the Mongoose document instance of the Standup model we just required, and as such, we now have access to the model's save method, note.save with a callback function where the first property is any errors that may be returned and the second the note document that was saved. We can test to see if there were any errors returned, and if so, notify the consumer of this API endpoint, returning a status of 400 and the err object as json otherwise we're good; and therefore, let's return a status of 200 and the actual note document as json. Just to save a little time, I'll paste in code for projects and team. The code is nearly identical to what we just looked at with the standup PUT endpoint, each requiring the respective model file and newing up an instance of the document from that model and then saving the JSON passed into the request body. Earlier in the course when we started developing this API server, we only asked the Express application to listen on the configured port, but so far, we haven't connected to MongoDB. It's time to do that now, or we won't get too far saving documents to MongoDB through Mongoose. We'll make those changes in the app.js file. First off, we need to bring in Mongoose, so const mongoose = require mongoose. Next, let's connect to Mongoose using the localhost connection string information as shown here. This information will need to change when we migrate to the cloud, by the way. Next is a reference to the mongoose.connection. It would be helpful to see if there were any errors upon connecting to MongoDB through Mongoose, and that's what this line does for us. Now once the database is open, in this callback function, we will logout to the console that we're connected to MongoDB, and then as before, as the Express app to start listening for the request on the port configured above. With all of those changes saved now, let's move over to the terminal window. Make sure that your local instance of MongoDB is running as it is in this terminal tab now, make sure you're in the server folder, and then run this Express API. We do that by entering yarn start here, and after a moment, we can see that the server is running on localhost port 8081. Now that the Express API server is running, we can test saving a document to it using Postman. Let's get that up and running now. Here in Postman, I have a test POST already set up in this Mongoose Course collection. Notice the URL is set to localhost port 8081/api/standup. On the Body tab here, notice the JSON object matches our Mongoose schema and therefore the model and documents built from that schema. I have some test data prefilled out here, and if we send this POST, we should see a status of 200 OK and the save document returned in the response body. To fully confirm this, let's open up Studio 3T and see if we can find this newly saved document. Once that opens and we get connected to local, we can open up the virtualstandups database and then the standups collection. This last entry should be the new one we just added via Postman, so we're good to go there.

Summary

In this module, we looked at some examples of how to build a model from a previously defined schema and discussed the arguments we pass into the Mongoose model method, which were a string, which represents the name of the model, and the schema object used to build the model from. Also, there was a third optional argument, which allows you to specify and override the name of a MongoDB collection document instance will be saved to. Next, we examined the relationship between models and documents in Mongoose and how those documents relate to MongoDB collection documents. We then looked at a slightly more complex example of populating the example quiz document with subdocuments. In the demo, we picked up where we left off with the standupSchema by building a model from that schema and then creating a document instance from that model, testing that all out in Postman. In the next module, we will take things one step further and learn to query data from MongoDB using these same models. I'll see you in the next module.