Getting Started with MongoDB & Mongoose ODM (Object Data Modeling) Library
Rate this video
00:00:00Introduction to Mongoose
- Introduction to Mongoose as an elegant MongoDB object modeling tool for Node.js.
- Explanation of Mongoose's role as an ODM library and its features.00:01:46Setting Up the Environment
- Instructions on setting up Node.js, installing Mongoose, and configuring the development environment.00:05:16Defining Schemas and Models
- Detailed explanation of creating Mongoose schemas and models, including field definitions and data types.00:11:59Inserting and Querying Data
- Demonstrating how to insert data into MongoDB using Mongoose and querying the inserted data.00:16:13Updating and Deleting Documents
- Overview of updating document fields and deleting documents using Mongoose methods.00:22:50Advanced Schema Options
- Discussion on setting required fields, defaults, and other advanced schema options in Mongoose.00:27:01Using Multiple Schemas
- Creating and using multiple schemas to manage related data and demonstrating the populate method.00:33:07Middleware and Final Thoughts
- Explaining the use of Mongoose middleware for pre-save actions and summarizing the benefits of using Mongoose with MongoDB.00:41:19Conclusion
- Final thoughts on the advantages of using Mongoose and encouragement to explore further with provided resources.The primary focus of the video is to teach viewers how to use Mongoose with MongoDB to create structured data models, perform database operations, and manage relationships between data in a Node.js environment.
🔑 Key Points
- Mongoose is an ODM library for MongoDB that simplifies data modeling, schema enforcement, and validation.
- It provides a semi-rigid schema structure, allowing for a balance between flexibility and data integrity.
- Mongoose schemas define the structure of documents within a collection, specifying field types and validation rules.
- Models in Mongoose are constructors compiled from schemas and manage CRUD operations for documents.
- The video demonstrates setting up a Node.js environment, installing Mongoose, and creating schemas and models.
- It covers querying, inserting, updating, and deleting documents using Mongoose methods.
- The video also explains how to use middleware for pre-save actions and how to reference other schemas within a model.
🔗 Related Links
Full Video Transcript
in this video we'll learn how mongoose a library for mongodb can help you to structure and access your data with ease many who learn mongodb get introduced to it through a very popular library mongoose what is mongoose was described as elegant mongodb object modeling for nodejs it's an odm or object data modeling library for mongodb with mongoose data modeling schema enforcement model validation and general data manipulation becomes effortless if you want to hear from the maintainer of mongoose valkarpov we had him on the mongodb podcast the episode link is in the description below now why mongoose by default mongodb has a flexible data model so flexible that anything goes this makes mongodb databases very easy to alter and update in the future but a lot of developers are used to having more rigid schemas now while everything that mongoose does can also be accomplished by using the mongodb driver for node.js mongoose abstracts some of the features of the mongodb drivers and wraps them up in a nice bow mongoose forces a semi-rigid schema from the beginning with mongoose we have to define a schema and a model so what's a schema a schema defines the structure of your collection documents a [ __ ] schema maps directly to a mongodb collection here's an example of a schema now with schemas we define each field and its data type permitted types are string number date buffer boolean mixed object id array decimal 128 and map now that we know what a schema is what is a model well models take your schema and apply it to each document in its collection models are responsible for all the document interactions like creating reading updating and deleting or crud it's important to note that the first argument passed to the model should be the singular form of your collection name mongoose automatically changes this to the plural form transforms it to lowercase and uses that for the database collection name so in this example the uppercase blog string translates to the lowercase blogs collection in mongodb then we also pass our blog schema schema object let's set up our environment i'm going to assume that you have node.js installed and vs code if you don't have those then go to nodejs.org and code.visualstudio.com to download and install the versions appropriate for your operating system so now in vs code let's open up our terminal and we're going to type npm init dash y that's going to initialize our project and accept all of the defaults next we'll install mongoose we'll also install nodemon as a dev dependency now let's go into our package.json and we're going to edit this script we have a test script let's change this to dev and we're going to have this start our index.js file using nodemon nodemon will monitor our project and after every save it will automatically restart it for us after this we're also going to add a type of module this is going to allow us to use es modules instead of common js this is also going to allow us to use top level await so let's save that and close it and now we'll need to create our index.js file we'll first import mongoose from mongoose and then we'll connect with mongoose now we'll need to give mongos a connection string you could connect to a local mongodb instance but we're going to use mongodb atlas if you don't already have an account go ahead and sign up for a free mongodb atlas cluster there's a link in the description below if you don't already have a cluster setup go check out my intro to atlas video to get your cluster created and set up once you have your cluster set up you can get your connection string from the mongodb atlas dashboard right here next to our cluster we'll click connect and then we'll click connect your application and this is our connection string let's copy this now back in vs code in our index.js file we'll paste this connection string notice here that it's already added my user and i'll just need to enter my password which i created during the cluster setup my password is super secret it's [ __ ] of course after this video i'll remove this user so this connection string is not going to work for you now the connection string will also reference the my first database database you can change this to whatever you'd like to call your database i'm just going to leave it now before we do anything with our connection we'll need to create a schema and model ideally you'll create a schema model file for each schema that is needed so we're going to create a new folder file structure so let's create that here we're going to create a model folder and then a blog.js file within that first let's import mongoose from mongoose then let's destructure the schema and the model from mongoose next we'll define our blog schema by creating a new mongoose schema and then we can define all of the fields that our documents should have so first we'll have a title and this is going to be of type string we'll also have a slug which will be of type string we'll have a published of boolean author will be of type string content of type string then we'll have tags which is going to be an array of strings so we define an array with square brackets and then the contents of the array could be anything but for this instance we're going to use strings we'll also have a created at and an updated app which are dates and then we'll add comments which is going to be an array of objects within each object we'll have a user content and votes the user and content will be strings and the votes a number lastly we'll define our blog model and we'll use the mongoose model and pass it to arguments the first is our collection remember for this mongoose automatically uses the plural lowercase version as our collection name so this is going to become the lowercase blogs collection in our mongodb database now for the second argument we pass our blog schema object and then let's export default our blog let's save this so now that we have our first model and schema set up we can start inserting data into our database so back in the index.js file let's insert a new blog article so first we need to import our blog model that we just created then we'll create a new blog object called article which will define the data that we want to save so within this we'll have our object which contains all of the data that we want to save and then we'll insert this article into our mongodb database by using the save mongoose method let's add a bit more after that to log what is currently in the database for this we're going to use the find one method so for our first article we're going to await blog.find1 we're going to pass an empty object which is going to find everything and find one is going to return the first thing that it finds so we're going to then console.log first article so let's run the code so be sure to save this and then let's open our terminal and we're going to run npm run dev remember we created this dev script and i received an error because blog did not specify the dot js so i added dot js saved it and now we have our new document logged now because we're using nodemon in this project every time we save the file the code is going to run again so if you want to insert a bunch of articles just keep saving so let's go back to our mongodb atlas dashboard and see what we have so we'll go here to browse collections now we'll see that we have a my first database database that was created and also a blogs collection now within the blogs collection we can see this document that we just inserted in the previous example we used the save mongoose method to insert a document into our database this requires two actions first we have to instantiate the object and then we save it now alternatively we can do this in one action using the mongoose create method so instead of creating a new blog let's say await blog dot create we'll still pass our object in and then we don't need to save it and we don't need to find again let's just console log our article let's open up our console and then let's save this and we'll see that it's going to rerun and we're going to get a new post and this time we have a new object id as well so if we go back to our dashboard and we refresh we should see this new document and there it is so this method is much better not only can we insert our document but we also get returned the document along with its id a mongoose makes updating data very convenient too expanding on this previous example let's change the title after it's been created so we're going to create another article exactly the same but now let's take our article and let's take the title and we're going to make that equal to something else let's say the most awesomest host now because we made a change to it we're going to need to save it so we're going to say await article dot safe and then we'll console log our article so let's open up our console so that we can see the log and then let's save the file and now we can see the most awesomest post and we have a new object id if we go back into our dashboard and refresh we'll see this third document and it's the most awesomest post it doesn't get much easier than that but this may not be what we intended to do so let's make sure that we're updating the correct document we're going to use a special mongoose method find by id this is going to get our document by its object id so let's copy this object id of the last one that we created and we don't want to create a new document we're going to say that article is going to await blog.find by id and then we have our object id then we're going to call the exec function or execute the exact mongoose function is technically optional and it returns a promise in my experience it's better to use this function since it will prevent some head scratching issues if you want to read more about it i'll include a link to the mongoose docs that talks more about this and promises so let's open up our terminal again and save the file so now we found our most awesomest post by our object id now there are many other query options in mongoose too you can check out the full list in the mongoose docs now just like with the standard mongodb node.js drivers we can project only the fields that we need so let's only get the title slug and content fields so we can do that in our find by id so first we're passing our object id and after that we can have an optional second parameter this second parameter could be an object a string or an array of strings so we're just going to use a string and we're going to say we want the title the slug and the content let's open up our terminal and save this again it's going to rerun and now we have our title our slug and our content and it's always going to also provide us with our id unless we specifically tell it not to just like in the standard mongodb node.js driver we have the delete one and delete many methods in mongoose so here we're going to await delete1 and we're going to search for the title of awesomepost delete1 is going to delete the first document that it finds that matches our query so then we're going to log blog and let's see what that does so let's open up our terminal and save our file and we see acknowledge true delete account one so it succeeded and deleted the first document that it found alternatively we also have delete mini which will delete every document that it finds that matches our query so if we save this we see that it found one more and it deleted it notice that the documents that we've inserted so far have not contained an author dates or comments so far we have defined what the structure of our document should look like but we have not defined which fields are actually required at this point any field could be omitted so let's set some required fields in our blog.js schema so right here title string is the exact same thing as changing this into an object and saying that our type is string so by turning this into an object we can then pass more parameters so let's also say required is true so now the title is required let's do the same thing for our slug we're going to have it be required but we're also going to say lowercase is going to be true a slug should always be in lowercase and so we want to make sure that in case some uppercase characters are passed we're going to automatically set those to lowercase now for published the type is boolean but we're not going to say it's required instead we're going to say that the default is false so if publish is not included it will automatically be added and set to false we'll also set the author to required we'll leave the content and tags just like they are but for created we're going to set a default for the created as well we're going to use an arrow function here because we want this to run every time a document is inserted so that is going to set this to the current date and time and we also want this to be immutable we don't want it to ever be changed so the date will be added when the document is inserted and it can never be updated after that and we'll leave updated at and comments just as they are for now and we'll move on so let's save this and then we're going to go back into our index.js and let's insert another document this time we'll need to include all of the required fields so it will include a title a slug and author content and tags let's open up our terminal and save the file now notice here that we have a created app field added for us i omitted the published field but now in our document we have published false that's because we set this as default in our schema and the slug is in lowercase even though i passed in some uppercase characters in the document object mongoose uses many standard mongodb methods plus introduces many extra helper methods that are abstracted from regular mongodb methods next we're going to go over just a few of those the exists method returns either null or the object id of a document that matches the provided query so in here we're going to say blog.exists and we're going to look for the author of jesse hall and then we'll console.log blog let's save this so now we can see that it was found and we're given the object id mongoose also has its own style of querying data the where method allows us to chain and build queries so instead of using this standard find method so we have blog.find1 we're looking for the author of jesse hall let's save this and we can see that we are returned that article instead of using the standard method we could use the equivalent where method so here we're going to say await blog.where author dot equals jesse hall and let's log blog where and we'll save this and we'll see that we returned that same article so either of these methods work use whichever seems more natural to you you can also chain multiple where methods to include even the most complicated query now to include projection when using the where method chain the select method after your query so after our query let's say select and then we're going to select our title and our author only let's save that and now we can see that we returned only our title and author along with the object id it's important to understand your options when modeling data if you are coming from a relational database background you're going to be used to having separate tables for all of your related data but generally in mongodb data that is accessed together should be stored together so you should plan this out ahead of time if possible nest data within the same schema when it makes sense but if you have the need for a separate schema mongoose makes it a breeze so let's create another schema so that we can see how multiple schemas can be used together we'll create a new file in our model directory we'll call this user.js first we're going to import mongoose from mongoose and then we're going to destructure our schema and model from mongoose and then we'll create a new user schema and then we're going to pass in our fields so first we're going to have a name and it's going to be of type string and it will be required we're also going to have an email this is going to be of type string we're also going to have a min length so this is another mongoose property that we can include so we're going to set the minimum length to 10. that sounds reasonable for an email address we're going to set it to required and email addresses should be in lowercase so we'll set that to true next we'll create our user model we'll pass in our model name and our user schema and then we'll export that as default so let's save that and now we need to reference this user model in our blog schema for the author and comments user so let's go over to our blog.js and now for author instead of string is going to be schematypes.object id now where does this schema types come from well let's go back up here and we actually need to import this from mongoose and we also need to add a ref or a reference so this is going to refer to our user model this is going to allow us to quote unquote join our data a bit later so let's include the same thing here for our user under comments so this is going to be a schema type of object id it's going to reference the user model and it will be required as well for every comment we'll save that and lastly let's go over to our index.js file and at the top we'll need to import our user model and then let's create a new user so we're going to say user await user.create and we'll give it a name and an email and then let's create a new article so we're going to say blog.create we'll say awesomepost3 and in the author field instead of a string this is going to be the user.id so we're creating this user and now we're going to get this user's id and pass it into this article so let's open up our terminal and save our file and now we see awesome post three and notice in the user field we just have our object id let's go back into our atlas dashboard as well let's refresh this and we should see here at the bottom that we have our author with our object id and notice over here a new collection called users and we have our new user as well so how do we get all of the info for our author along with the article well we can use the populate mongoose method back in vs code let's find our article so we're going to say article is going to await blog.find1 we're going to look for the title of awesome post 3 and now we're going to populate and we're going to specify which field we want to populate that is the author field let's open up our terminal we'll save our file and now let me expand this and now we can see we have our article and the author data is all populated within the article as well mongoose actually uses the mongodb dollar lookup method behind the scenes to get this data in mongoose middleware are functions that run before and or during the execution of asynchronous functions at the schema level let's look at an example of this we're going to update the updated at date every time an article is saved or updated we're going to add this into our blog.js model so back on our blog.js file after our schema we're going to say blog schema.pre and then pass in save so this is going to be before we save and now we have a function and this function is given a next method so we're going to say this dot updated at is going to equal date.now and then we're going to call next to move on now back in our index.js file we're going to find an article we're going to find it by id so i've grabbed one of the ids from our articles then we're going to say article.title is going to equal updated title then we're going to await the save and then console log the article so let's open up our terminal we're going to save our files and now we've never set any updated at dates but notice that we now have an updated at date that was all done through the schema now besides pre there's also a post mongoose middleware function i think that our example here could use another schema for the comments so try creating that schema and testing it and adding a few users and comments now there are many other great mongoose helper methods that are not covered here so be sure to go check out the official documentation for references and more examples i'll include a link in the description i think it's great that developers have many options for connecting and manipulating data in mongodb whether you prefer mongoose or the standard mongodb drivers in the end it's all about the data and what is best for your application and your use case i can see why mongoose appeals to many developers and i think i'll be using it a lot more in the future as well if this video helped you out give it a like and subscribe for more videos like this you