How to Create Virtuals in Mongoose: Simple Guide
In Mongoose, you create a virtual property using
schema.virtual('name') and define a getter function with .get(). Virtuals let you add fields that are computed dynamically and not saved in the database.Syntax
To create a virtual in Mongoose, use schema.virtual('virtualName') to define the virtual field. Then use .get(function() { ... }) to specify how to compute its value.
This virtual field will not be saved in the database but will appear when you convert documents to JSON or objects.
javascript
const mongoose = require('mongoose'); const schema = new mongoose.Schema({ firstName: String, lastName: String }); schema.virtual('fullName').get(function() { return this.firstName + ' ' + this.lastName; });
Example
This example shows how to create a virtual property fullName that combines firstName and lastName. The virtual is accessible like a normal property but is not stored in MongoDB.
javascript
const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ firstName: String, lastName: String }); userSchema.virtual('fullName').get(function() { return this.firstName + ' ' + this.lastName; }); const User = mongoose.model('User', userSchema); const user = new User({ firstName: 'Jane', lastName: 'Doe' }); console.log(user.fullName);
Output
Jane Doe
Common Pitfalls
- Virtuals are not saved to the database, so they won't appear if you query raw MongoDB.
- By default, virtuals do not show up in
toJSON()ortoObject()outputs unless you enable them in the schema options. - Trying to set a virtual property without a setter will not change the underlying data.
javascript
const mongoose = require('mongoose'); const schema = new mongoose.Schema({ firstName: String, lastName: String }, { toJSON: { virtuals: true }, toObject: { virtuals: true } }); schema.virtual('fullName').get(function() { return this.firstName + ' ' + this.lastName; }); // Without the toJSON/toObject options, fullName won't appear in JSON output const user = new mongoose.model('User', schema)({ firstName: 'John', lastName: 'Smith' }); console.log(JSON.stringify(user)); // fullName missing console.log(JSON.stringify(user.toJSON())); // fullName included
Output
{"firstName":"John","lastName":"Smith"}
{"firstName":"John","lastName":"Smith","fullName":"John Smith"}
Quick Reference
Remember these key points when working with Mongoose virtuals:
- Use
schema.virtual('name').get(fn)to define a virtual getter. - Virtuals are not stored in MongoDB.
- Enable
{ toJSON: { virtuals: true }, toObject: { virtuals: true } }in schema options to include virtuals in output. - You can also define setters with
.set(fn)if needed.
Key Takeaways
Create virtuals with schema.virtual('name').get(function) to add computed fields.
Virtuals do not save data to MongoDB but appear in document objects.
Enable virtuals in JSON output with schema options { toJSON: { virtuals: true } }.
Virtual setters allow modifying underlying data through virtual properties.
Without enabling virtuals in output, they won't appear when converting documents to JSON.