cooklang / cooklang/federation
/api/search pagination.total reports the page window, not the true match count
- Dominant language
- Rust
- Stars
- 17
- Forks
- 4
- Avg merge
- 5m
- Merged PRs (30d)
- 1
Description
## Problem
`SearchIndex::search` (`src/indexer/search.rs`) computes the total match count from the already-truncated result set:
```rust
let top_docs = searcher
.search(&*tantivy_query, &TopDocs::with_limit(limit + offset))?;
// Get total count
let total = top_docs.len();
```
`TopDocs::with_limit(limit + offset)` caps the collector at the current page window, so `top_docs.len()` saturates at `limit + offset` rather than counting all matching documents.
## Effect
- `total` and `total_pages` are wrong for any query matching more documents than one page holds.
- It grows as you paginate deeper, which reads as a moving target: `?page=5&limit=100` reports `total: 500` regardless of how many recipes actually match.
- `total_pages` (`total.div_ceil(limit)`) is derived from it, so pagination controls in the web UI are wrong too.
Reproduce:
```bash
curl -s 'http://localhost:3000/api/search?q=&limit=100&page=1' | jq .pagination # total: 100
curl -s 'http://localhost:3000/api/search?q=&limit=100&page=5' | jq .pagination # total: 500
```
## Suggested fix
Use Tantivy's `Count` collector for the true total, alongside `TopDocs` for the page:
```rust
use tantivy::collector::{Count, TopDocs};
let (top_docs, total) = searcher.search(
&*tantivy_query,
&(TopDocs::with_limit(limit + offset), Count),
)?;
```
`Count` scores nothing and just counts matches, so the extra cost is small.
## Context
Found during end-to-end verification of recipe locale detection (#11). Pre-existing and unrelated to locale — left out of scope there.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in src/indexer/search.rs at SearchIndex::search and reproduce the issue with the provided curl and jq commands. Check the pagination response for a query spanning more than one page; done means total reflects all matching documents and total_pages remains consistent across page requests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, search
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100