MongoDB Sort, Limit and Skip

MongoDB sort, limit and skip are cursor methods that control the order and number of documents returned. They are what you need for "latest posts", "top 5 products" and paging through results.

sort()

1 sorts ascending and -1 descending. You can sort by several fields; the order of keys matters.

db.products.find({}, { _id: 0, name: 1, price: 1 }).sort({ price: -1 })
[
  { name: 'Coffee Beans', price: 22 },
  { name: 'Olive Oil', price: 18.75 },
  { name: 'Almonds', price: 15 },
  { name: 'Basmati Rice', price: 12.5 },
  { name: 'Honey', price: 11.5 },
  { name: 'Green Tea', price: 6 },
  { name: 'Dark Chocolate', price: 4.25 }
]

limit()

limit(n) returns at most n documents. Combined with sort it gives a top-N list.

db.products.find({}, { _id: 0, name: 1, stock: 1 })
  .sort({ stock: -1 })
  .limit(3)
[
  { name: 'Dark Chocolate', stock: 500 },
  { name: 'Green Tea', stock: 300 },
  { name: 'Basmati Rice', stock: 120 }
]

skip() for Pagination

skip(n) jumps over n documents. Page p with size s is skip((p - 1) * s).limit(s).

const page = 2, size = 3
db.products.find({}, { _id: 0, name: 1 })
  .sort({ name: 1 })
  .skip((page - 1) * size)
  .limit(size)
[ { name: 'Dark Chocolate' }, { name: 'Green Tea' }, { name: 'Honey' } ]

Range-Based Pagination

Large skip values are slow because MongoDB still walks the skipped documents. For big collections remember the last value seen and query past it, which uses an index efficiently.

db.products.find({ name: { $gt: "Honey" } }, { _id: 0, name: 1 })
  .sort({ name: 1 })
  .limit(3)
[ { name: 'Olive Oil' } ]

Frequently asked questions

In which order does MongoDB apply sort, skip and limit?

Always sort first, then skip, then limit, regardless of the order you chain the methods.

What order does find() return without sort()?

Natural order, which is not guaranteed. Always use sort() if order matters.

Why does my sort fail with a memory error?

Sorts without an index are limited to 100 MB of memory. Add an index on the sort fields or use allowDiskUse in aggregation.