cooklang / cooklang/federation

/api/search pagination.total reports the page window, not the true match count

Open Beginner friendly
#13 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.