suppose I have following mongoose schema in Node.js
var schema = new mongoose.Schema({
views:Number,
clicks:Number,
ctr:Number
})
In which I want that CTR attribute should be automatically calculated by a formula based on values of other attributes, i.e lets say
ctr = clicks / views
I don't want to have CTR as a virtual field because based on the value of CTR I will sort all documents of my collection and apparently sorting is not possible based on virtual fields. So I was wondering if there is any way to have calculated attributes in mongoose schema which gets automatically updated on update of any of the dependent attribute/field
You can also set the default schema option to a function. Mongoose will execute that function and use the return value as the default. const schema = new mongoose.Schema ( { views: { type: Number }, clicks: { type: Number }, ctr: { type: Number, default: function () { return this.clicks / this.views } } })
As you can see, the we're using the populate function of mongoose to join the documents when querying for Posts. The first call to populate joins the Users for the postedBy property of the posts whereas the second one joins the Users for the comments. In contrast, the query result is a full document containing all User references for the Posts.
When using a NoSQL database like MongoDb, most of the time you'll have documents that contain all properties by itself. But there are also scenarios where you might encounter the need for a more relational approach and need to reference other documents by the ObjectIds.
I want that CTR attribute should be automatically calculated by a formula based on values of other attributes
From the Mongoose docs [emphasis added]:
You can also set the default schema option to a function. Mongoose will execute that function and use the return value as the default.
Therefore, your example could be rewritten as:
const schema = new mongoose.Schema({
views: {
type: Number
},
clicks: {
type: Number
},
ctr: {
type: Number,
default: function() {
return this.clicks / this.views
}
}
})
So I was wondering if there is any way to have calculated attributes in mongoose schema which gets automatically updated on update of any of the dependent attribute/field
If I understand correctly, note the section in the docs on the setDefaultsOnInsert
option. This may be of relevance when recalculating the default upon update.
You can use for it virtual field:
var schema = new mongoose.Schema({
views:Number,
clicks:Number
})
schema.virtual('ctr')
.get(function() {
return this.clicks / this.views;
});
You can do anything, but don't forget about that that difficult thing slower your server.
In my case for calculating age user I do that.
const mongoose = require( 'mongoose' );
const Schema = mongoose.Schema;
const userSchema = new Schema( {
born: {
type: String,
get: a => {
let date = new Date(a);
let today = new Date();
let timeDiff = today.getTime() - date.getTime();
let age = Math.floor( timeDiff / ( 1000 * 3600 * 24 ) / 365 );
return age;
},
set: age => age,
alias: 'age',
},
}
);
module.exports = mongoose.model( 'User', userSchema );
And Mongoose Documantation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With