querydrill

Learn ›Advanced aggregation ›Facets, dates and full problems

Paging and total count in one query

$count$facet$limit$match$skip$sort

Every paginated API needs the same two things: this page of rows, and how many rows there are in total. $facet gets both in one query instead of two, and this is the single most reused $facet recipe there is.

Suppose your API needs:

{
  "data": [...],
  "total": 1000
}

You can do:

db.orders.aggregate([
  {
    $match: {
      status: "completed"
    }
  },

  {
    $facet: {
      data: [
        {
          $sort: {
            createdAt: -1
          }
        },
        {
          $skip: 20
        },
        {
          $limit: 10
        }
      ],

      total: [
        {
          $count: "count"
        }
      ]
    }
  }
])

Output:

{
  data: [
    // 10 orders
  ],

  total: [
    {
      count: 1000
    }
  ]
}

This is a pattern worth remembering.

Practise this

1 exercise