Mongoose is an Object Data Modeling (ODM) library for Node.js that provides a way to interact with MongoDB databases. It allows you to define data schemas, perform queries, and provides other helpful features that make it easier to work with MongoDB.
In this article, we'll go through the steps of installing and setting up Mongoose, defining a schema, performing basic CRUD operations, and using some of Mongoose's other features.
Installation and Setup
To get started, make sure you have Node.js and MongoDB installed on your system. You can download and install Node.js from the official website (https://nodejs.org/) and MongoDB from the official website (https://www.mongodb.com/).
Once you have Node.js and MongoDB installed, you can install Mongoose using npm:
npm install mongoose
After installing Mongoose, you can create a new Node.js project and create a file to connect to MongoDB using Mongoose:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_database', {
useNewUrlParser: true,
useUnifiedTopology: true
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('Connected to MongoDB!');
});
In the code above, we first require Mongoose and then use the mongoose.connect() method to connect to a MongoDB database named "my_database". We also pass in some options to ensure compatibility with newer versions of MongoDB. Finally, we set up some event listeners to log any errors or successful connections to the console.
Defining a Schema
Before we can start performing operations on our data, we need to define a schema that will represent the structure of our data. In Mongoose, a schema is a blueprint for defining the shape of documents in a MongoDB collection. Here's an example of how to define a simple schema for a "users" collection:
const userSchema = new mongoose.Schema({
name: String,
email: String,
age: Number,
isVerified: Boolean
});
const User = mongoose.model('User', userSchema);
In the code above, we define a new userSchema object that contains four fields: name, email, age, and isVerified. We then use the mongoose.model() method to create a new model called User, which represents the "users" collection in our database.
Performing CRUD Operations
With our schema defined, we can now start performing CRUD (Create, Read, Update, Delete) operations on our data. Here are some examples of how to perform basic CRUD operations using Mongoose:
Create
To create a new user, we can use the User.create() method:
const newUser = new User({
name: 'John Doe',
email: 'john.doe@example.com',
age: 25,
isVerified: true
});
newUser.save(function(err) {
if (err) return console.error(err);
console.log('User created successfully!');
});
In the code above, we create a new User object using the schema we defined earlier, set its properties, and then call the save() method to save it to the database. If there are no errors, we log a success message to the console.
Read
To retrieve all users, we can use the User.find() method:
User.find(function(err, users) {
if (err) return console.error(err);
console.log(users);
});
In the code above, we call the User.find() method with no arguments, which returns all documents in the "users" collection. The callback function receives two arguments: an error object and an array of documents. If there are no errors, we log the array of documents to the console.
To retrieve a specific user by ID, we can use the User.findById() method:
User.findById('601eb30ed41b3e2d74c27362', function(err, user) {
if (err) return console.error(err);
console.log(user);
});
In the code above, we call the User.findById() method with the ID of the user we want to retrieve. The callback function receives two arguments: an error object and the document with the matching ID. If there are no errors, we log the document to the console.
Update
To update a user's information, we can use the User.updateOne() method:
User.updateOne({ name: 'John Doe' }, { age: 26 }, function(err, result) {
if (err) return console.error(err);
console.log(result);
});
In the code above, we call the User.updateOne() method with two arguments: a filter object that matches the user we want to update, and an update object that sets the new value for the user's age field. The callback function receives two arguments: an error object and the result of the update operation. If there are no errors, we log the result to the console.
Delete
To delete a user, we can use the User.deleteOne() method:
User.deleteOne({ name: 'John Doe' }, function(err) {
if (err) return console.error(err);
console.log('User deleted successfully!');
});
In the code above, we call the User.deleteOne() method with a filter object that matches the user we want to delete. The callback function receives an error object. If there are no errors, we log a success message to the console.
Other Features
Mongoose provides several other features that can make working with MongoDB easier. Here are a few examples:
Validation
Mongoose allows you to define validation rules for your data, ensuring that it meets certain requirements before it is saved to the database. Here's an example of how to define validation rules for the email field in our userSchema:
const userSchema = new mongoose.Schema({
name: String,
email: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
match: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/
},
age: Number,
isVerified: Boolean
});
In the code above, we add several properties to the email field to enforce validation rules. The required property ensures that the field is not empty, the unique property ensures that no two documents have the same email address, the trim property removes any whitespace before or after the email address, the lowercase property converts the email address to lowercase, and the match property enforces a regular expression pattern that matches valid email addresses.
Virtuals
Mongoose allows you to define virtual properties that are not stored in the database but are calculated on-the-fly. Virtual properties are useful when you need to calculate a value based on other properties in the document. Here's an example of how to define a virtual property for our userSchema:
const userSchema = new mongoose.Schema({
name: String,
email: String,
age: Number,
isVerified: Boolean
});
userSchema.virtual('isAdult').get(function() {
return this.age >= 18;
});
In the code above, we define a virtual property called isAdult using the virtual() method on our userSchema object. The get() method is used to define the behavior of the virtual property, in this case, to return a boolean value indicating whether the user is an adult (age >= 18).
We can then access the isAdult property just like any other property on a User document:
const user = new User({
name: 'John Doe',
email: 'johndoe@example.com',
age: 25,
isVerified: true
});
console.log(user.isAdult); // true
Middleware
Mongoose provides middleware functions that allow you to intercept and modify document operations. Middleware functions are useful when you need to perform some action before or after a document is saved or deleted. Here's an example of how to define a middleware function for our userSchema:
userSchema.pre('save', function(next) {
console.log('Saving user...');
next();
});
userSchema.post('save', function(doc) {
console.log('User saved:', doc);
});
In the code above, we define two middleware functions using the pre() and post() methods on our userSchema object. The first middleware function is called before a document is saved, and the second middleware function is called after a document is saved. In this case, the functions simply log some messages to the console.
Plugins
Mongoose provides plugins that allow you to extend the functionality of your models. Plugins are useful when you need to reuse a set of functionality across multiple models. Here's an example of how to define a plugin for our userSchema:
const mongoosePaginate = require('mongoose-paginate-v2');
userSchema.plugin(mongoosePaginate);
In the code above, we load the mongoose-paginate-v2 plugin and apply it to our userSchema using the plugin() method. The mongoose-paginate-v2 plugin adds pagination functionality to our User model.
Conclusion
In this article, we've covered the basics of using Mongoose with Node.js and MongoDB. We started by discussing what Mongoose is and why it's useful, and then we walked through the process of setting up a connection to a MongoDB database and defining a schema for our data. We also covered how to perform CRUD operations using Mongoose, and we explored some of the other features that Mongoose provides, such as validation, virtuals, middleware, and plugins.
With Mongoose, you can easily work with MongoDB in a structured and consistent way, making it an essential tool for any Node.js developer working with MongoDB.