pedrommuller
pedrommuller

Reputation: 16066

Calculating average inside a Mongoose hook

I want to calculate an average every time a new element is added to a collection. Basically, what I'm trying to calculate is inside a "pre save" hook, but I'm always getting undefined results.

This is the schema:

var CommentSchema = new Schema({
    posted:{
        type:Date,
        default:Date.now
    },
    text:{
        type: String
    },
    owner:{
            _id:{ 
                type: Schema.Types.ObjectId, ref: 'User'
            },
            displayName:{ 
                type:String 
            }
    },
    reference: {
        objectType:{
            type: String,
            enum: [ 'document','element','process', 'project', 'story']
        },
        _id:{ 
            type: Schema.Types.ObjectId 
        }
    },
    sentiment:{
        score:{
            type:Number,
            default:0.0
        },
        comparative:{
            type:Number,
            default:0.0
        }
    }
});

CommentSchema.pre('save', function(next){
        var thiz = this; 
        // this code is inside another callback, that's the reason I'm using thiz
        if(thiz.reference.objectType ==='element'){
            mongoose.models['Comment'].aggregate([
            { $match:{'reference._id': mongoose.Types.ObjectId(thiz.reference._id)} },
            { $group:{'reference._id': mongoose.Types.ObjectId(thiz.reference._id), average:{$avg:'$sentiment.score'}}}
            ],
            function(err, result){
                console.log('------------------');
                console.log('result',result);
                console.log('------------------');
            }               
            );
        }
        next();
});

I always get undefined results, however, if I query like the example below, I get the list of comments.

db.getCollection('comments').find({"reference._id":ObjectId("55a69276242aa1837a1ecb6c")})

Is there anything I am missing in the aggregate?

Upvotes: 1

Views: 255

Answers (1)

Ebubekir Dirican
Ebubekir Dirican

Reputation: 386

{ $group: { _id: null, average: { $avg: '$sentiment.score' } } }

"The _id field is mandatory; however, you can specify an _id value of null to calculate accumulated values for all the input documents as a whole."

http://docs.mongodb.org/manual/reference/operator/aggregation/group/

$group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

Upvotes: 1

Related Questions