Getting Started with Mongoose Virtuals
May 11, 2019
Mongoose virtuals are computed properties on Mongoose documents. They are not stored in MongoDB: a virtual property is computed whenever you access it.
Suppose you have a BlogPost
model that stores the raw markdown content of a blog post. You can create a virtual html
that automatically calls a markdown parser for you whenever you access the html
property.
// Markdown parser
const marked = require('marked');
const blogPostSchema = new Schema({ content: String });
// A _virtual_ is a schema property that is **not** stored in MongoDB.
// It is instead calculated from other properties in the document.
blogPostSchema.virtual('html').get(function() {
// In the getter function, `this` is the document. Don't use arrow
// functions for virtual getters!
return marked(this.content);
});
const BlogPost = mongoose.model('BlogPost', blogPostSchema);
const doc = new BlogPost({ content: '# Hello' });
doc.html; // "<h1 id="hello">Hello</h1>"
Why would you use a virtual instead of a method? Because you can configure Mongoose to include virtuals when converting a Mongoose document to JSON, including when using Express' res.json()
function.
const app = require('express')();
const axios = require('axios');
// Make Mongoose attach virtuals whenever calling `JSON.stringify()`,
// including using `res.json()`
mongoose.set('toJSON', { virtuals: true });
app.get('*', function(req, res) {
// Mongoose will automatically attach the `html` virtual
res.json(doc);
});
const server = app.listen(3000);
// "<h1 id="hello">Hello</h1>"
await axios.get('http://localhost:3000').then(res => res.data.html);
The downside of virtuals is that, since they aren't stored in MongoDB, you can't use them in queries.
Want to become your team's MongoDB expert? "Mastering Mongoose" distills 8 years of hard-earned
lessons building Mongoose apps at scale into 153 pages. That means you can learn what you need
to know to build production-ready full-stack apps with Node.js and MongoDB in a few days.
Get your copy!
Did you find this tutorial useful? Say thanks by starring our repo on GitHub!