Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I include a virtual field in API response using Mongoose?

How do I include a virtual field in a JSON response

const ItemSchema = mongoose.Schema({
  name: String,
  time: { type: Date, default: Date.now }
});

ItemSchema.virtual('timeleft').get(function() {
  this.timeleft = 24
 
  var currentTime = moment(); 
  var timeStored = moment.utc(this.time).local().format(); 
  this.timeleft -= currentTime.diff(timeStored, 'h');

  
});

API call

app.get('/getAllItems', function(req, res, next) {
   Item.find({}, function(err, items) {
     res.json(items);
   });
});

So technically the response won't include virtual timeleft field. Am I missing something?

[
 {
   name: "nike",
   time: "21/2/22"

  },

  {
   name: "adidas",
   time: "21/2/22"

  },
]
like image 203
sinusGob Avatar asked Jan 14 '17 07:01

sinusGob


People also ask

What is virtual field in Mongoose?

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

Are Mongoose virtual functions stored in MongoDB?

Virtuals are document properties that do not persist or get stored in the MongoDB database, they only exist logically and are not written to the document's collection.

What is findById in Mongoose?

In MongoDB, all documents are unique because of the _id field or path that MongoDB uses to automatically create a new document. For this reason, finding a document is easy with Mongoose. To find a document using its _id field, we use the findById() function.

What is ORM in Mongoose?

Mongoose is similar to an ORM (Object-Relational Mapper) you would use with a relational database. Both ODMs and ORMs can make your life easier with built-in structure and methods. The structure of an ODM or ORM will contain business logic that helps you organize data.


2 Answers

// use Schema like this        
const ItemSchema = new Schema({
    name: String,
    time: { type: Date, default: Date.now }
}, {
    toObject: { virtuals: true },
    toJSON: { virtuals: true }
});

ItemSchema.virtual('timeleft').get(function() {
    // this.timeleft = 24
    var currentTime = moment();
    var timeStored = moment.utc(this.time).local().format();
    console.log(" ====== 000 ======== ", currentTime.diff(timeStored, 'h'))
    return this.timeleft = currentTime.diff(timeStored, 'h');
});

const Item = mongoose.model('Item', ItemSchema);

new Item({
    name: 'Axl'
}).save((err, result) => { 
    console.log("=== err ", err, "=== result ", result)
});

Item.find({}, function(err, items) {
    console.log("=========", items)
});
like image 181
Manjeet Thakur Avatar answered Oct 11 '22 16:10

Manjeet Thakur


According to Mongoose docs Mongoose virtuals are not stored in MongoDB, which means you can't query based on Mongoose virtuals.

// Will **not** find any results, because `domain` is not stored in
// MongoDB.
const doc = await User.findOne({ domain: 'gmail.com' });
doc; // undefined

If you want to query by a computed property, you should set the property using a custom setter or pre save middleware.

like image 37
Suhayb Avatar answered Oct 11 '22 16:10

Suhayb