Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose toObject: { virtuals: true }

I'm trying to learn MongoDB/Node and I noticed that in a schema I often see something like this:

toObject: { virtuals: true }
toJSON: { virtuals: true }

What do these two lines mean?

like image 606
saeho Avatar asked Nov 13 '14 13:11

saeho


People also ask

What are virtuals in Mongoose?

In Mongoose, a virtual is a property that is not stored in MongoDB. Virtuals are typically used for computed properties on documents.

What does it mean that Mongoose is an ODM?

Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node. js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.

What is Mongoose model explain with example?

A Mongoose model is a wrapper on the Mongoose schema. A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc.

What does $Set do in Mongoose?

The $set operator replaces the value of a field with the specified value. The $set operator expression has the following form: { $set: { <field1>: <value1>, ... } } To specify a <field> in an embedded document or in an array, use dot notation.


1 Answers

This is not "MongoDB" but specific to the mongoose ODM.

Mongoose has a concept of "virtual" fields in the schema definition. This essentially allow this (blatant glean from documentation):

var personSchema = new Schema({
    name: {
        first: String,
        last: String
    }
});

var Person = mongoose.model( "Person", personSchema );

But suppose you just want to "store" those properties but then have something you can access in code called "fullname". This is where "virtuals" come in:

personSchema.virtual("name.full").get(function () {
    return this.name.first + ' ' + this.name.last;
});

Now we can do something like this:

var bad = new Person({
    name: { "first": "Walter", "last": "White" }
});

console.log("%s is insane", bad.name.full); // Walter White is insane

So the name.full does not actually exist in the data, it's just a schema representation in code. But of course "tied" to a function that uses the actual data present in the object to make a method that returns a value combining the two fields per the code in the method.

This is basically what "virtual" fields are about. They are actually "methods" defined on the document "object" that present a value that is not "stored" or persisted in the database. Usually they are based on actual persisted values from the data storage.

But to really clear up your direct question. Mongoose only 'serializes' the content of it's internal object structure based on the "stored" fields by default. So what those two lines "really" mean are:

  1. toObject(): This produces a "plain" or "raw" representation of the object data without all the other "mongoose magic" parts of the extended object. But the purpose of "virtuals" is to make those methods part of the object returned. Basically just the plain object, called as:

     var model = Model.new({ "name": { "first": "Walter", "last": "White" });
     console.log( model.toObject() );
    
  2. toJSON(): You can call this method explicitly and just as shown above, but it's most common usage is from a JSON parser like below where it is implicitly called. The same principles apply as above. The "virtuals" includes the result of those methods in the serialized output, such as:

     var model = Model.new({ "name": { "first": "Walter", "last": "White" });
     JSON.stringify( model, undefined, 2 );
    

So the second case there is an "implicit" call of the .toJSON() method on the object. What the configuration is doing is telling that method to not only include data or "fields" present in the object, but also the "virtual" methods defined and the output they give as well. Same for .toObject().

like image 142
Neil Lunn Avatar answered Sep 21 '22 08:09

Neil Lunn