Urgent.News

What's breaking now, across thousands of outlets.

Tech

Paginate search results properly with Whoosh (offset, total, and "page 3 of 12")

Part of an ongoing series on Whoosh , the pure-Python full-text search library I maintain. Almost every search UI needs pages: ten hits, a "Next" button, and a little "Showing 21–30 of 214" label. It's easy to hand-roll this with results[20:30] , and it's easy to get it subtly wrong — off-by-one offsets, a "Next" button that shows an empty page, or a total count that's actually just the size of…

Whoosh is a pure-Python full-text search library that offers a convenient helper function called `Searcher.search_page` for pagination. This function simplifies the process of creating paginated search results, making it easy to implement features like a "Next" button and a "Showing X–Y of Z" label.

To use `search_page`, you first create a `Searcher` instance with your index directory and then call `search_page` with your query, page number, and page length. The function returns a `ResultsPage` object that contains metadata for the current page, including the total number of matching documents, the current page number, the total number of pages, and the offset for the current page.

When displaying the paginated results, you can iterate over the `ResultsPage` object like a normal result set. The `total` attribute gives you the total number of hits, the `pagenum` attribute shows the current page number (1-based), `pagecount` indicates the total number of pages, `pagelen` is the number of hits on the current page, and `offset` provides the zero-based index of the first hit on the current page.

The "Showing N–M of Z" label can be generated by adding 1 to the `offset` and then adding the `pagelen` to get the end value. To indicate whether the "Next" button should be hidden, you can use the `is_last_page()` method of the `ResultsPage` object.

This helper function also handles edge cases gracefully. If a user tries to access a non-existent page, such as by manipulating the URL, Whoosh will automatically clamp the page number to the last available page, preventing crashes or empty lists. Additionally, a pagenum of 0 or a negative value will raise a `ValueError`, so it's important to validate page numbers in your application.

Using `search_page` is more efficient than slicing a `Results` object directly because it only computes the necessary results for the requested page. Under the hood, `search_page` performs a search with a limit of `pagenum * pagelen`, so the first page is cheap to compute. However, keep in mind that deep pagination (e.g., page 500) will cost as much as fetching the first 5,000 hits, as this is inherent to the nature of ranked search and not a specific issue with Whoosh.

In scenarios requiring infinite scroll over enormous result sets, consider using cursor-based pagination instead of deep page numbers.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

More from Thursday 24 September →