Search code examples
mongodbmongoosemongoose-populate

Populate limited number of items in array, but keep array length - mongoose


With the schema

var CommentSchema = new Schema({
  text: { type: String },
  replies: [{ type: mongoose.Schema.ObjectId, ref: 'Comment' }]
});

I have a query like

Comment.findById(req.params.id)
  .populate({
    path: 'replies',
    model: 'Comment',
    options: {
      limit: 2
    }
  })
  .exec(...)

Now I see no option to populate a limited number of elements in an array and keep the length of the array.

I thought about populating to a different "target" field, so that the original replies-array remains untouched (and therefore the information about the number of replies). But I think this option doesn't exist in mongoose populate().

The use-case can be seen on Youtube comments. A comment includes the number of replies, but only displays a limited number of them.


Solution

  • I used the following trick to handle this situation.

    var idToSearch = mongoose.Types.ObjectId(req.params.id)
    
    var aggregation = [
        {$match : {_id : idToSearch}},
        {$project : {
          _id : 1,
          replies: {$slice : ['$replies',5]},
          totalreplies : {$size : "$replies"},
        }}
      ];
    models.Comment.aggregate(aggregation)
        .exec(function(err, comments) {
          if(err){
            // return error 
          }
          else if(!comments){
            // return data not found
          }else {
            models.Comment.populate(comments,
              { path: 'replies'},
              function(err, populatedComments){
                if(err){
                  // return error
                }
                else {
                  console.log('comments ',populatedComments);
                }
              });
          }
        });
    

    Hope it helps