How to Check current user's vote before votes are grouped and sumed in same aggregate function

107 Views Asked by At
var PostSchema = new mongoose.Schema({
    item: {
    type: mongoose.Schema.ObjectId,
        ref: 'item',
        required: true
    },
  user: {
    type: mongoose.Schema.ObjectId,
    ref: 'User',
    required: true
  },
  vote: {
    type: Number,
    default: 0
  },
  total: {
    type: Number,
    default: 0
  },
  awsPostKey: {type: String},
  picture: {type: String, required: true}
});

var data = function(){
return Post
.find({})
.then(function(post){
    return post;
 })
};


var userId = //mongo objectId for current user

//postVote schema:
var PostVoteSchema = new mongoose.Schema({
  post: {
    type: mongoose.Schema.ObjectId,
        ref: 'Post',
        required: true
    },
  user: {
    type: mongoose.Schema.ObjectId,
    ref: 'User',
    required: true
  },
  vote: {
    type: Number,
    default: 0
  }
});

//pass data from Post query to PostVote sum function:

PostVoteSchema.statics.sum = function (data, userId) {

 var postIds = data.map(function (a) {
    return a._id;
  });

return PostVote
.aggregate(
    [
   { $match: { 'post': {$in: postIds}}},
   { $group: { _id:'$post' ,vote:{$sum:'$vote'}}}
 ])
.execAsync()
.then(function(votes){

    return votes;

   //desired output to client, _id is for specific post
   {_id: 5802ea4bc00cb0beca1972cc, vote: 3, currentUserVote: -1}

 });
};

I'm successfully able to get the total sum of all votes with the same postId. Now, I"m wanting to see if the current user (userId) has placed a vote for the given post as well, then to return how they voted (+1 or -1) along with the sum of all votes for the specific post.

Is it possible to do this, or will I have to do this outside of my aggregate pipeline -- within a second query? It just seems potentially taxing to have to query the collection again.

1

There are 1 best solutions below

7
chridam On

Yes, that's possible. Within the $group pipeline, you can use the $cond operator as the logic for feeding the $sum accumulator operator. For example:

return PostVote.aggregate([
   { "$match": { "post": { "$in": postIds } } },
   { 
        "$group": {
            "_id": "$post",
            "votes": { "$sum": "$vote" },                 
            "userVotes": {
                "$sum": {
                    "$cond": [
                        { "$eq": ["$user", userId] },
                        "$vote",
                        0
                    ]
                }
            }
        }
    }
 ]).execAsync().then(function(votes){
    return votes;
});