Pagination and Sorting
Search results page 1 shows ten books. The shopper clicks "next", then "sort by price: low to high". Behind those two buttons are three small keys in the search body: from, size and sort.
The rule
from skips, size takes, sort orders — and deep pages need search_after.
Pagination. size is how many hits to return (default 10). from is how many to skip first (default 0). Page n with page size s starts at from = (n − 1) × s:
GET /books/_search
{
"from": 20,
"size": 10,
"query": { "match": { "title": "garden" } }
}That is page 3. The reply also tells you the total count in hits.total, which you can use to draw page numbers.
There is a ceiling: from + size may not exceed 10,000 by default (index.max_result_window), because each shard must collect and sort from + size hits for every request — deep pages get expensive. For "infinite scroll" or exporting everything, use search_after: sort the results, then pass the sort values of the last hit you received to fetch the next batch. Pair it with a point in time so the pages come from a consistent snapshot while new documents arrive.
Sorting. By default hits are ordered by _score, best first. sort changes that:
GET /books/_search
{
"query": { "term": { "genre": "fiction" } },
"sort": [
{ "price": "asc" },
{ "published": "desc" }
]
}Cheapest first; ties broken by newest. Each hit now carries a sort array with the values used — exactly what search_after needs. Two rules:
- Sort on
keyword, numeric, date or boolean fields. Sorting on atextfield fails; use its keyword sub-field. - When you sort by a field, relevance scores are not computed, so
_scorecomes back asnullunless you ask for"track_scores": true.
The shortcut
For paging, compute from = (page − 1) × size, then check from + size ≤ 10,000. For sorting, list keys from most to least important, and always end with a unique tie-breaker (such as an ID field) so equal values do not reshuffle between pages.
Compute from
(4 − 1) × 25 = 75. So
from: 75,size: 25.
Drills
Answer fast — trust the rule.
With size: 20, what from value returns page 5?
A request with from: 9995 and size: 10 fails. Why?
Sorting by title, a text field, returns an error. What fixes it?
You sort by price and every hit shows "_score": null. What is going on?
Remember
- from skips, size takes, sort orders — and deep pages need search_after.
- from = (page − 1) × size, and from + size stays within 10,000.
- Sort on keyword, number or date fields, and end with a unique tie-breaker.
