Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose sum fields from populated documents

I have two models: User and Track. User can complete and get points for every Track.

User schema:

let userSchema = new mongoose.Schema({
    name: {type: String, required: true},
    completedTracks: [{
        type: mongoose.Schema.ObjectId,
        ref: 'Track',
    }],
});

Track schema:

let trackSchema = new mongoose.Schema({
  points: {
    type: Number,
    default: 0,
  }
});

I am storing references to completed tracks in User model.

What I want to do is to query for multiple users, display only _ids of tracks completed by each of them and add information about total points scored within a new score property.

Example of a result I would like to achieve:

[
    {
        "completedTracks": [
            "5a9f14f18e04b3225953954c",
            "5aa5a8fa7367661c03f57a99",
            "5aa1aa5a7da9fd2946b01c04"
        ],
        "name": "Person 1",
        "score": 42,
        "id": "5aaab2c63d1a9d182b183a01"
    },
    {
        "completedTracks": [],
        "name": "Person 2",
        "score": 0,
        "id": "5aaab602c5bdc411d3cef3bd"
    }
]

I tried to create virtual that would return the score but it does not work as user.completedTracks are just ObjectIds

userSchema.virtual('score').get(function() {
    return this.completedTracks.reduce((acc, doc) => acc + doc.points, 0);
});
like image 921
umat Avatar asked Mar 16 '18 21:03

umat


1 Answers

You can try below aggregation in 3.4.

$lookup to look up the points for completed tracks followed by $addFields to return a score field summing the points and $project with exclusion to drop the lookup-data field from response.

UserModel.aggregate([
  {"$lookup":{
    "from":"tracks", // name of the foreign collection
    "localField":"completedTracks",
    "foreignField":"_id",
    "as":"lookup-data"
  }},
  {"$addFields":{
    "score":{
      "$sum":"$lookup-data.points"
    }
  }},
  {"$project":{"lookup-data":0}}
])
like image 131
s7vr Avatar answered Sep 23 '22 14:09

s7vr