Problem
SearchIndex::search (src/indexer/search.rs) computes the total match count from the already-truncated result set:
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:
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:
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.
Problem
SearchIndex::search(src/indexer/search.rs) computes the total match count from the already-truncated result set:TopDocs::with_limit(limit + offset)caps the collector at the current page window, sotop_docs.len()saturates atlimit + offsetrather than counting all matching documents.Effect
totalandtotal_pagesare wrong for any query matching more documents than one page holds.?page=5&limit=100reportstotal: 500regardless 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:
Suggested fix
Use Tantivy's
Countcollector for the true total, alongsideTopDocsfor the page:Countscores 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.