115 lines
4.3 KiB
Markdown
115 lines
4.3 KiB
Markdown
# FTS5 Full-Text Search — Execution Board
|
|
|
|
**Feature:** Add true full-text search (FTS5) to Recipe Manager
|
|
**Created:** 2026-03-30
|
|
**Status:** Planning → In Progress
|
|
**Orchestrator:** Cleo (main agent)
|
|
**Target Model:** stepfun/step-3.5-flash (where applicable)
|
|
|
|
---
|
|
|
|
## 🎯 Goal
|
|
|
|
Replace the current `LIKE`-based search with a high-performance, relevant FTS5 virtual table that indexes:
|
|
- Recipe titles and descriptions
|
|
- Ingredient items and notes
|
|
- Step instructions
|
|
- Tag names (via recipe_tags join)
|
|
|
|
Provide a single backend search endpoint that:
|
|
- Supports phrase queries, prefix searches, AND/OR logic
|
|
- Returns ranked results by relevance
|
|
- Preserves pagination metadata
|
|
- Falls back gracefully if FTS fails
|
|
|
|
---
|
|
|
|
## 📦 Deliverables
|
|
|
|
1. **Schema & Migration**
|
|
- Add `recipes_fts` virtual table (FTS5) with `title`, `description`, `ingredient_item`, `ingredient_notes`, `step_instruction`, `tag_name` columns
|
|
- Create triggers to keep FTS in sync on INSERT/UPDATE/DELETE of recipes, ingredients, steps, tags, recipe_tags
|
|
- Backfill existing data in migration
|
|
|
|
2. **Backend Search Endpoint**
|
|
- New route: `GET /api/recipes/search`
|
|
- Params: `q` (query string), `page`, `limit`
|
|
- Uses `MATCH` with `bm25()` ranking
|
|
- Returns `{ results, total, page, limit, hasMore }` consistent with existing list endpoint
|
|
|
|
3. **Frontend Integration**
|
|
- Update search input to call new endpoint instead of filter-based search
|
|
- Show ranked order (highest relevance first)
|
|
- Preserve existing pagination UI
|
|
|
|
4. **Tests**
|
|
- Unit tests for FTS trigger logic (insert/update/delete sync)
|
|
- Backend integration tests: search relevance, phrase queries, no-results, pagination
|
|
- E2E test: search returns expected recipes by title/ingredient
|
|
|
|
5. **Migration & Rollback**
|
|
- Ensure `schemaVersion` increment and migration applied
|
|
- Document rollback steps (drop virtual table + triggers)
|
|
|
|
---
|
|
|
|
## 🔢 Task Breakdown
|
|
|
|
| Task | Owner | Est. (hrs) | Status |
|
|
|------|-------|------------|--------|
|
|
| T1: Design FTS5 virtual table schema + trigger plan | Sub-agent 1 | 1.5 | ⏳ |
|
|
| T2: Implement migration (create FTS, triggers, backfill) | Sub-agent 2 | 2 | ⏳ |
|
|
| T3: Build `/api/recipes/search` endpoint with ranking | Sub-agent 3 | 2 | ⏳ |
|
|
| T4: Write backend unit/integration tests for FTS/sync | Sub-agent 4 | 2 | ⏳ |
|
|
| T5: Update frontend to use new endpoint + pagination | Sub-agent 5 | 1.5 | ⏳ |
|
|
| T6: E2E verification: search by title, ingredient, tags | Sub-agent 6 | 1 | ⏳ |
|
|
| T7: Rollback plan, doc updates, final review | Sub-agent 7 | 1 | ⏳ |
|
|
|
|
---
|
|
|
|
## 🧩 Dependencies
|
|
|
|
- T3 depends on T2 (endpoint requires schema)
|
|
- T4 depends on T2 (tests need DB structure)
|
|
- T5 depends on T3 (frontend calls endpoint)
|
|
- T6 depends on T5
|
|
- T7 depends on all
|
|
|
|
Tasks T1 and T2 can run in parallel (T1 designs, T2 starts once design is signed).
|
|
|
|
---
|
|
|
|
## 📐 Acceptance Criteria
|
|
|
|
- ✅ FTS5 virtual table present and populated with all existing recipes
|
|
- ✅ Search returns recipes ranked by BM25 (most relevant first)
|
|
- ✅ Phrase queries ("chocolate chip cookies") match correctly
|
|
- ✅ Prefix searches ("choc") work
|
|
- ✅ Ingredient-only searches return correct recipes
|
|
- ✅ Pagination metadata consistent with list endpoint
|
|
- ✅ All tests pass (including new FTS tests)
|
|
- ✅ Rollback documented and tested (optional)
|
|
|
|
---
|
|
|
|
## 🛠️ Technical Notes
|
|
|
|
- Use `CREATE VIRTUAL TABLE recipes_fts USING fts5(...)`
|
|
- Triggers: `AFTER INSERT/UPDATE/DELETE` on recipes, ingredients, steps, tags, recipe_tags
|
|
- Use `content=''` and `content_triggers` to auto-sync if desired; but explicit triggers may be simpler
|
|
- Migration must be idempotent (check if FTS exists before creating)
|
|
- Backend: parameterized query `SELECT ... FROM recipes_fts WHERE recipes_fts MATCH ?`
|
|
- Rank: `bm25(recipes_fts)` ascending (lower score = better)
|
|
- Join back to `recipes` table to fetch full recipe objects
|
|
|
|
---
|
|
|
|
## 🧠 Success Metric
|
|
|
|
Search accuracy > current `LIKE` filter, no regressions in performance, tests green.
|
|
|
|
---
|
|
|
|
**Orchestration Plan:**
|
|
Main agent will spawn seven independent sub-agents (one per task) with clear primitives. Sub-agents will report back with status updates. Main agent will monitor progress and roll up into a final status. Use `stepfun/step-3.5-flash` for all sub-agents where model choice applies (per instruction).
|