Virtual Properties, Instance Methods & Static Model Methods0%

Virtual Properties, Instance Methods & Static Model Methods

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Virtual Properties, Instance Methods & Static Model Methods

Mongoose allows adding domain behavior directly to your data models. Instead of scattering helper functions throughout controllers, you can attach Virtual Properties (computed properties not stored in MongoDB), Instance Methods (actions on a single document), and Static Methods (queries on the entire model).


1. Virtual Properties (Computed Attributes)

A Virtual Property is a logical field that can be read and written like a normal property, but is never persisted to the MongoDB database:

JavaScript
import { Schema, model } from 'mongoose';
 
const userSchema = new Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
birthDate: { type: Date, required: true }
}, {
// Ensure virtuals are included when converting to JSON or Objects
toJSON: { virtuals: true },
toObject: { virtuals: true }
});
 
// Define virtual getter for 'fullName'
userSchema.virtual('fullName').get(function() {
return `${this.firstName} ${this.lastName}`;
});
 
// Define virtual getter for calculated 'age'
userSchema.virtual('age').get(function() {
const diffMs = Date.now() - this.birthDate.getTime();
const ageDt = new Date(diffMs);
return Math.abs(ageDt.getUTCFullYear() - 1970);
});

Virtual properties cannot be queried directly with Model.find({ fullName: '...' }) because they do not exist on disk in MongoDB!


2. Instance Methods (methods)

An Instance Method is a custom function available on every individual document instance:

JavaScript
import bcrypt from 'bcrypt';
 
// Method to verify passwords during authentication
userSchema.methods.comparePassword = async function(candidatePassword) {
// 'this.password' contains the stored bcrypt hash
return await bcrypt.compare(candidatePassword, this.password);
};
 
// Method to generate a password reset token
userSchema.methods.createPasswordResetToken = function() {
const resetToken = crypto.randomBytes(32).toString('hex');
this.passwordResetToken = crypto.createHash('sha256').update(resetToken).digest('hex');
this.passwordResetExpires = Date.now() + 10 * 60 * 1000; // 10 minutes
return resetToken;
};

3. Static Methods (statics)

A Static Method is a custom function attached directly to the compiled Model itself, ideal for specialized queries:

JavaScript
// Custom static method to find top-rated active courses
courseSchema.statics.getFeaturedCourses = function(limit = 6) {
// 'this' refers to the Course model
return this.find({ isPublished: true, rating: { $gte: 4.5 } })
.sort('-rating')
.limit(limit)
.populate('instructor', 'name avatar');
};
 
// Invoking static method:
const topCourses = await Course.getFeaturedCourses(10);

Interactive Quiz

Multiple Choice Questions

Question 1
Where are Mongoose Virtual Properties stored?
Question 2
Why can't you run User.find({ fullName: 'Sumit Sharma' }) when fullName is defined as a Mongoose virtual?
Question 3
What is the difference between an Instance Method and a Static Method in Mongoose?
Question 4
Which schema option must be set to ensure virtual fields are displayed when sending a document via res.json(user)?
Question 5
In an instance method userSchema.methods.getTier = function() { ... }, what does this point to?

Next Lesson

One-to-Few (Embedded) vs One-to-Many (Referenced) Data Modeling

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext