Virtual fields in mongoose
Introduction
In this article we are going to learn how to use virtual fields in mongoose.
What is mongoose virtuals?
In Mongoose, a virtual is a property that is not stored in MongoDB. Virtuals are typically used for computed properties on documents.
Example
Suppose you have a User
schema . In that User
schema you have a firstname
and lastname
fields, but you also want fullname
of user.
By using mongoose virtuals you can easily get fullname
field without storing
it in MongoDb.
Below is one way to implement the fullname
property using a virtual. You define virtuals on a schema using the Schema.virtual()
function.
const userSchema = new mongoose.Schema({
firstname:string,
lastname:string
});
// create a virtual property 'fullname' that's computed from 'firstname' and 'lastname'.
userSchema.virtual('fullname').get(function(){
return `${this.firstname} ${this.lastname}`
});
const Users = new mongoose.model("User");
let user = new Users({ firstname:"john",lastname:"cena"}).save()
// 'fullname' is now a property on User documents
user.fullname; // john cena
Virtual Setters
You can also use virtuals to set multiple properties at once. For example, suppose you have two string properties: firstname
and lastname
. You can create a virtual property fullname
that lets you set both of these properties at once. The important thing to remember is that here this
refers to the document the virtual is attached too.
const userSchema = new mongoose.Schema({
firstname:string,
lastname:string
});
// create a virtual property 'fullname' with the getters and setters
userSchema.virtual('fullname').get(function(){
return `${this.firstname} ${this.lastname}`
})
.set(function (fullname){
const firstname = v.substring(0, v.indexOf(' '));
const lastname = v.substring(v.indexOf(' ') + 1);
this.set({ firstname, lastname });
});
const Users = mongoose.model("User", userSchema);
const user = new User();
// Vanilla JavaScript assignment triggers the setter
user.fullname = 'john cena';
user.fullname; // 'john cena'
user.firstname; // 'john'
user.lastname; // 'cena'
Virtuals in JSON
By default mongoose does not include virtuals in json, when you send the document in express res.json().
To send the virtuals in json you need to set the toJSON
schema option to { virtuals: true }
const userSchema = new mongoose.Schema({
firstname:string,
lastname:string
},{ toJSON: { virtuals: true } });
const user = Users.findOne();
user.fullname; // john cena
Note: If you use the lean option, that means your queries return POJOs( plain old javascript object ) rather than full Mongoose documents. That means no virtuals if you use lean().
const userSchema = new mongoose.Schema({
firstname:string,
lastname:string
},{ toJSON: { virtuals: true } });
const user = Users.findOne().lean();
user.fullname; // undefined