Node Mongoose Tutorial – How to use Node.js with Mongoose
What is Mongoose?
Mongoose is an ODM(Object Data Modelling) Library made for NodeJS and MongoDB Database, it enables users to create and manage relationships between data by mapping objects from MongoDB to NodeJS and managing the schema validations for the data.
MongoDB is a very flexible database since it is a NoSQL Database, which works on the concept of storing documents as just JSON Objects, however, to perform basic schema validations and manage the data easily we would need a library like Mongoose to rescue us.
Terminologies to Know Before Getting Started!
Schema
- We do know that MongoDB is a schema-less database but still, we need to define the schema of the application user using mongoose for validation purposes, schema just means the overall structure and how the data is organized in the database.
Database
- Database in MongoDB means the same as other SQL Languages but here we just store a set of collections so we can say a Database in MongoDB is just a group of collections having documents
Collection
- When we study SQL we often deal with tables in the database, here we have collections, now a collection just means the group of documents stored all together.
Document
- In SQL we know that there are columns and tables, in NoSQL databases like MongoDB there is no such thing so how do we store data? Well here we use something called Document, a Document is just a record stored inside Collection using a JSON object.
Field
- In NoSQL databases like MongoDB, we use key-value pairs inside a JSON object to store any particular data field, now inside each Document, there can be single or multiple data fields that contain some data.
Models
- Models in our context will be just high-level functions that will take defined schema and create an instance of the MongoDB document
Prerequisites
- You must have MongoDB Installed or an account in the MongoDB Atlas cloud infrastructure of theirs to connect the database with mongoose or NodeJS
- You must have NodeJS installed in the system
Getting Started with Mongoose ODM
First of all, you will need to install the mongoose library using npm on your device using the below command
npm install mongoose --save
Code language: JavaScript (javascript)
once this is done, we can import this module in js files and start working with mongoose
create an empty project using npm and then import the module in the js file
npm init -y
Code language: JavaScript (javascript)
we need to create a JavaScript file and start writing our code, first of all, let’s see how we can connect our MongoDB with NodeJS using mongoose.
const mongoose = require("mongoose");
mongoose.connect(
"mongodb://localhost:27017/test_database",
() => {
console.log("Connected to MongoDB")
},
err => {
console.log(err);
}
);
Code language: JavaScript (javascript)
mongoose.connect()
takes the first argument as URI for connection which you can get from localhost or MongoDB Atlas if you are connected via a cloud instance of MongoDB, since this is just for educational purposes we are not using environment variables otherwise in production we do not expose the DB URI like this. The second argument takes the callback function which is logging so that we know we are connected otherwise we log the error in the following function.
Even if you do not define all the arguments in connect function still it will work the same since MongoDB won’t start executing commands until it is connected with the Database until then commands will be queued, however, by logging the result, we get to know what is happening visually.
Let’s Create Schema with Mongoose
for example, I am creating this file named MySchema.js
const mongoose = require("mongoose00");
const mySchema = new mongoose.Schema({
firstName: String,
lastName: String
});
module.exports = mongoose.model("MySchema", mySchema);
Code language: JavaScript (javascript)
Now, let’s test if the schema works or not
const mongoose = require("mongoose");
const MySchema = require("./MySchema.js");
mongoose.connect(
"mongodb://localhost:27017/test",
() => {
console.log("Connected to MongoDB")
},
err => {
console.error(err);
}
);
async function test() {
const x = new MySchema(
{
firstName: "Naman",
lastName: "Thanki"
}
);
await x.save();
console.log(x);
}
test();
Code language: JavaScript (javascript)
As you can see in the image shown above that it creates an _id
field in the document by default which is a type of ObjectId
in MongoDB
Schema Types in Mongoose
Schema Types in mongoose take care of how a field should behave, what data item it is supposed to accept, and what data items are valid for that particular field path.
There are multiple Schema Types that we can make use of and create efficient schema modeling using mongoose. However, we won’t need most of them at the beginning level.
String, Number, Date, Boolean, Array, and ObjectId
are the ones that you would use most when you are just starting to learn mongoose.
Example
const mongoose = require("mongoose");
const mySchema = new mongoose.Schema({
firstName: String,
lastName: String,
userAge: Number,
createdAt: Date,
updatedAt: Date,
anotherObject: mongoose.SchemaTypes.ObjectId,
someFlag: Boolean,
arrayOfStrings: [String],
nestedObject: {
someProperty: String,
otherProperty: Number
}
});
module.exports = mongoose.model("MySchema", mySchema);
Code language: JavaScript (javascript)
As you can see in the above example, these are the basic types we can make use of using Mongoose, and we can also have objects in schema just like we do in MongoDB.
It’s clear how to use these types from the example. However, if you leave the [ ]
brackets empty for arrays, it would be considered any type, but you can specify the type there as well as I did.
Read More about SchemaTypes from Mongoose Docs.
Validating Your Schema Types
What we did in the previous section works fine but suppose let’s say you want a field that has some constraints like it must be required and not null, well for that we assign our field with an object that has constraints.
Example
const mongoose = require("mongoose");
const mySchema = new mongoose.Schema({
firstName: String,
lastName: String,
userAge: {
type: Number,
min: 13,
max: 25,
required: true,
validate: {
validator: value => value !== 17,
message: props => `Not accepting users whose age is ${props.value}`
}
},
createdAt: {
type: Date,
immutable: true,
default: () => Date.now()
},
updatedAt: {
type: Date,
default: Date.now()
},
anotherObject: mongoose.SchemaTypes.ObjectId,
someFlag: Boolean,
arrayOfStrings: [String],
nestedObject: {
someProperty: String,
otherProperty: Number
}
});
module.exports = mongoose.model("MySchema", mySchema);
Code language: JavaScript (javascript)
As you can see above, we are putting all the constraints as an object such as min, max
whose meanings are self-explanatory, and then we have required
, which means that field must be required otherwise we won’t be able to create that document, and immutable
the flag means that once a value is given it will never change just like how we have types like Strings in programming languages which are immutable. then for default
in the above example every time I am getting the current Date but you can give any default value you wish to.
We also have a validate
property to add a custom validator to our field, here I have used a function that checks if the user’s age is not 17, then we have a message
property that will be displayed when you violate this validator function so if you try to create a user with 17 age it will throw that error message.
More validations and examples can be found here
Finding the Documents
Now that we have the basics done and have our schema set up, let’s see how we can find documents!
Example
async function findDocuments() {
let result = await MySchema.find({ firstName: "Naman" });
console.log(result);
result = await MySchema.findOne({ firstName: "Naman" });
console.log(result);
result = await MySchema.exists({ firstName: "Naman" });
console.log(result);
result = await MySchema.findById("63712d28b82e1b080ad1a6db");
console.log(result);
result =
await MySchema
.where("userAge")
.gt("17")
.lt("20")
.where("firstName")
.equals("Naman");
console.log(result)
}
Code language: JavaScript (javascript)
The find
the method works the same as MongoDB’s find query however there are more ways to find documents.
We have the findOne
method which exactly returns the first found object that is queried for, and the exists
method checks if the queried item exists or not, we also have an alternative approach to find documents such as the method where()
in mongoose which lets you chain the functions and write a query in that way as I have shown in example’s last line.
Updating the Documents
There are various methods of updating documents in mongoose. This one is a basic example where we update using id and then make changes.
You can learn more about this from Mongoose Docs
Example
async function updateDocument() {
const id = "63712d28b82e1b080ad1a6db";
const result = await MySchema.findByIdAndUpdate(id, { firstName: "Aman"});
console.log(result);
}
Code language: JavaScript (javascript)
Deleting the Documents
Just like other methods, for deleting a document we have multiple choices. However, we will stick to deleteOne
as of now.
Example
async function deleteDocument() {
const result = await MySchema.deleteOne({ firstName: "Aman" });
console.log(result);
}
Code language: JavaScript (javascript)
Instance Methods and Virtual in Mongoose
Inside MySchema.js
we can define instance methods which means on every instance those methods can be called and run, we can also define static methods which means they run on the entire model.
Another critical thing to consider is that you cannot use arrow functions here because that’s how mongoose has designed it and you must use the function keyword.
Example
mySchema.methods.testMethod = function() {
console.log(`This Works!`);
}
mySchema.statics.findByLastName = function(lastName) {
return this.find({ lastName: new RegExp(lastName, "i") });
}
Code language: JavaScript (javascript)
async function testMethods() {
const result = await MySchema.findByLastName("Thanki");
console.log(result);
}
Code language: JavaScript (javascript)
Virtual Properties
Virtual in Mongoose are properties that let you put getters and setters and are not stored on MongoDB. Now let’s say we have the first and last name of a user, we do not need to keep their full name because we can take advantage of virtual property.
mySchema.virtual("fullName")
.get(function() {
return `${this.firstName} ${this.lastName}`;
})
Code language: JavaScript (javascript)
result = await MySchema.findOne({ firstName: "Naman" });
console.log(result);
console.log(result.fullName);
Code language: JavaScript (javascript)
Wrap Up
We have covered almost all the basics that we need to get started with mongoose using NodeJS but that’s not all, you can always keep yourself up to date with the latest documentation, so keep learning and make use of all the basics that we’ve covered!
Sharing is caring
Did you like what NAMAN THANKI wrote? Thank them for their work by sharing it on social media.
No comments so far
Curious about this topic? Continue your journey with these coding courses: