Skip to content

Add fuzzy search fallback (exact first, fuzzy on zero hits) - #477

Open
detournemint wants to merge 5 commits into
chilli-axe:masterfrom
detournemint:fuzzy-search-fallback
Open

Add fuzzy search fallback (exact first, fuzzy on zero hits)#477
detournemint wants to merge 5 commits into
chilli-axe:masterfrom
detournemint:fuzzy-search-fallback

Conversation

@detournemint

@detournemint detournemint commented Aug 1, 2026

Copy link
Copy Markdown

What this does

Currently a search that doesn't exactly match a card name returns nothing — precise mode requires the whole string to match, and even Fuzzy (Forgiving) mode requires every word to match exactly, so typos ("brainstrom") and extra words ("the lightning bolt") yield zero results.

This PR adds a retry-on-miss fallback on both search stacks:

  • Client search (Orama): when a search returns zero hits, it retries once with Levenshtein tolerance: 2. The retry decision is made at the aggregate level across indexes, so an exact hit in one index suppresses fuzzy matches from others.
  • Backend (Elasticsearch): when a search returns zero hits, it escalates through two retries — fuzziness: AUTO with all words required, then minimum_should_match: "2<75%" to also tolerate extra words. Applies to both the editor search and explore search endpoints.

Behavior is unchanged whenever the primary search finds at least one result (no pre-existing test snapshots changed). All filters (source, DPI, tags, size) still apply to fallback queries. Fallback retries are best-effort: on ES transport errors the original empty result is returned rather than a new error path.

Implementation notes

  • searchOramaIndex is extracted from the worker into a pure oramaSearch.ts module so the search logic is unit-testable outside the worker
  • No index mapping changes, no API schema changes

Testing

  • 10 Jest tests for the Orama search module (typos, extra words, partials, filter preservation during fallback, multi-index behavior)
  • 6 pytest cases against real Elasticsearch via testcontainers (editor + explore fallback paths, filters respected during fallback)
  • Full chromium Playwright e2e suite passes

Related: #478 (Explore artist filtering) touches some of the same search plumbing — whichever lands second will need a trivial rebase.

🤖 Generated with Claude Code

detournemint and others added 4 commits July 31, 2026 22:43
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a search returns zero hits, retry once with Levenshtein tolerance
so typos, extra words, and near-misses still find cards. Extracts
searchOramaIndex into its own module so the search logic is testable
outside the worker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a search matches nothing, retry with escalating forgiveness:
first with typo tolerance (fuzziness AUTO, all words required), then
also tolerating extra words (minimum_should_match 75%). Applies to both
the editor search and explore search endpoints. Filters always apply to
fallback queries, and no index mapping changes are needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Reformat with prettier 2.7.1 to match the repo's pinned pre-commit hook
- Hoist the client-side fallback decision from per-index to aggregate
  level so an exact hit in one index suppresses fuzzy matches from
  others (new searchOramaIndices API, with multi-index tests)
- Make the explore view's fallback best-effort like the editor path
- Use minimum_should_match 2<75% so one- and two-word queries still
  require every word during the extra-words fallback
- Broaden fallback retry catch to TransportError
- Type the explore search closure and document fallback_level

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@detournemint
detournemint force-pushed the fuzzy-search-fallback branch from 7d566eb to 8a6be09 Compare August 1, 2026 03:54
@detournemint detournemint changed the title Add fuzzy search fallback and Explore artist filtering Add fuzzy search fallback (exact first, fuzzy on zero hits) Aug 1, 2026
@detournemint

Copy link
Copy Markdown
Author

This branch now includes the test-determinism commit from #480 so CI runs green independently; once #480 merges, this PR rebases down to just its own changes.

@detournemint
detournemint force-pushed the fuzzy-search-fallback branch from 807be79 to 92bd9f6 Compare August 1, 2026 04:49
- Reset factory sequences before every test so snapshots no longer
  depend on which tests run or in what order. Previously, adding any
  test shifted sequence-generated values (e.g. artist names) in every
  later test's snapshot, breaking unrelated tests. Regenerates the six
  affected snapshots.
- Skip Moxfield URL tests when MOXFIELD_SECRET is not configured and
  update_database tests when client_secrets.json is absent or invalid,
  so fork PRs (which receive no repo secrets) and credential-less local
  runs pass instead of erroring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@detournemint
detournemint force-pushed the fuzzy-search-fallback branch from 92bd9f6 to 2bad262 Compare August 1, 2026 05:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant