Script Valley
MongoDB: Complete Course
Mongoose and Node.js IntegrationLesson 5.5

Mongoose virtuals, statics, and instance methods

virtual properties, get and set virtuals, virtual populate, schema statics, instance methods, toJSON virtuals, schema options

Virtual properties — computed, not stored

Mongoose virtual property

Virtuals are properties derived from other document fields at access time. They are never persisted to MongoDB. They live only in the JavaScript runtime as computed getters or setter functions on the document object.

// Virtual getter — computed from stored fields
userSchema.virtual('fullName').get(function () {
  return `${this.firstName} ${this.lastName}`
})

// Make virtuals appear in JSON serialization (e.g. res.json())
userSchema.set('toJSON', { virtuals: true })

const user = await User.findById(id)
console.log(user.fullName) // 'Ada Lovelace' — not in MongoDB document

Instance methods — called on a document instance

Instance methods are functions added to the document prototype. Inside the method, this refers to the specific document object it was called on. Use them for document-level business logic like password comparison or permission checks.

// Define the method
userSchema.methods.comparePassword = async function (candidate) {
  return bcrypt.compare(candidate, this.password)
}

// Use it on a fetched document
const user = await User.findOne({ email: 'ada@example.com' })
const valid = await user.comparePassword('secret123') // true or false

Statics — called on the Model class

// Define the static — 'this' is the Model
userSchema.statics.findByEmail = function (email) {
  return this.findOne({ email: email.toLowerCase() })
}

// Call it on the Model directly
const user = await User.findByEmail('ADA@EXAMPLE.COM')