Node Mongoose Tutorial – How to use Node.js with Mongoose

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 --saveCode 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 -yCode 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)
Our Data is Saved in the Database

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

Validation in Mongoose

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)
Our data is updated and change is reflected

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)
The first found item is deleted

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)
We have our full name printed

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.

0/10000

No comments so far