My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Virtual fields in mongoose

Asmit shrivastava's photo
Asmit shrivastava
·Jun 14, 2021·

2 min read

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