Sort a result according to the size of an array with Mongoose

Solution 1:

What about this:

        db.collection.aggregate([  { $addFields:{ len:{$size:"$room.RoomActorLikes"}}}    , {$sort:{len:-1}} ,{$skip: skip},
{$limit: limit}  ])

Detailed example:

       db.collection.aggregate([
      {
        $match: {
              UserStatus: "Success"
                }
      },
      {
       $addFields: {
             len: {
              $size: "$room.roomActorLikes"
                  }
             }
      },
      {
        $sort: {
              len: -1
               }
       },
       {
          $skip: 1
        },
       {
          $limit: 3
       },
       {
          $project: {
                   len: 0
                    }
       }
      ])

explained:

  1. $match -> Here reduce the amount of documents down to the ones that are with UserStatus-> Success in $match stage or if there is more conditions better so the amount of documents that need to be processed in later stages to be smaller. ( Best is to have index on this field so if you have too many documents this to reduce the processing as much as possible )

  2. $addFields -> Create new field len that will contain the number of array elements in document array to be easy to sort later.

  3. $sort -> Sort in descending order ithe documents based on array counts.

  4. $skip the number of documents to display as part of your paging action.

  5. $limit the number of ducuments to display as part of your paging action.

  6. $project to remove the len field if you dont need in the final output ( this is optional since you may not consider it from the app side )

playground

Abit more safer option $addFields->$size , preventing error messages in case of missing RoomActorlikes or missing room field from the main document:

          {
           $addFields: {
          len: {
    $size: {
      $cond: {
        if: {
          $eq: [
            {
              $type: "$room.roomActorLikes"
            },
            "missing"
          ]
        },
        then: [],
        else: "$room.roomActorLikes"
        }
       }
     }
    }
   }

playground safe option ( checking if RoomActorLikes exist )