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!