5

I have 2 fields on on Mongoose model: totalAttempts and totalRight. I am planning to calculate accuracy based on them.

totalAttempts: {
    type: Number,
    default: 1
},
totalRight: { 
    type: Number,
    default: 1
}

This is what I have done [it doesn't work]

 accuracy:{
     type:Number,
     required:function() {return (this.totalRight/this.totalAttempts*100).toFixed(2)}
}

Also, if I don't put default value on Accuracy I get an error:

ERROR; While creating new question ..ValidationError: Path `accuracy` is require                      d.

events.js:163

What will be the right way to accomplish this ? I already have a working solution to get totalAttempts and totalRight every time user request that Model. But I want to save that calculation and store info on my database.

Sandip Subedi
  • 1,039
  • 1
  • 14
  • 34

3 Answers3

5

Pre save is the right way to go. Add it to your schema.

ModelSchema
.pre('save', function(next){
  this.accuracy = this.totalRight/this.totalAttempts*100).toFixed(2)
  next();   
});

Change accuracy definition to:

accuracy: {
     type: Number
}
Talha Awan
  • 4,573
  • 4
  • 25
  • 40
  • I am still getting ERROR; While creating new question ..ValidationError: Path `accuracy` is required. events.js:163 throw er; // Unhandled 'error' event ^ MongooseError: Question validation failed – Sandip Subedi May 13 '17 at 18:26
  • 1
    I suppose you meant `default` by `required` in your question. So, you if you remove required from accuracy it should work. `pre save` is called after the validations are run. That's why in your case `required` validation is failing. – Talha Awan May 13 '17 at 18:34
2

You don't need to calculate it before you save the document. You just need to add a virtual field that gets the value of accuracy when you need it

yourSchema.virtual("accuracy").get(function () {
    return this.totalRight/this.totalAttempts*100).toFixed(2)
});

now when you query this document you will get accuracy but don't forget to use .toJSON({ virtuals: true }) on your document query


for more about virtuals in mongoose check mongoose virtuals. when using lean use this plugin mongoose-lean-virtuals.

Ha Kim
  • 76
  • 3
1

try this :

 accuracy:{
     type: Number,
     required:true,
     default: function() {
     return (this.totalRight/this.totalAttempts*100).toFixed(2)
}}