P PasteCode
Prompt

Prompt pour ajouter la recherche plein texte PostgreSQL

Prompt IA copier-coller pour ajouter la recherche plein texte native PostgreSQL avec tsvector, index GIN et résultats classés à une application Next.js existante.

CursorClaude CodeCodexWindsurf Next.jsPostgreSQLTypeScript
.md .json Difficulté: Moyen Mis à jour 8 juin 2026

Utilisez ce prompt pour ajouter une véritable recherche plein texte PostgreSQL à une application existante — en utilisant tsvector, un index GIN et ts_rank — sans que l’agent ait recours à Elasticsearch, Algolia ou une API de recherche tierce.

Prompt principal

Main Prompt
You are working in a Next.js App Router project with TypeScript and PostgreSQL (using the
`postgres` npm package, not Prisma or Drizzle).
Task: add full-text search over the `posts` table (columns: id, title, body, created_at).
Database changes:
1. Write a migration file `migrations/0010_add_fts.sql` that:
- Adds a generated column: `search_vector tsvector GENERATED ALWAYS AS
(to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,''))) STORED;`
- Creates a GIN index: `CREATE INDEX posts_search_idx ON posts USING GIN (search_vector);`
2. Do NOT use `pg_trgm` or LIKE queries — use `@@` with `to_tsquery` or `websearch_to_tsquery`.
Application changes:
- Create `src/lib/search.ts` with a `searchPosts(query: string, limit = 20)` function that:
- Uses `websearch_to_tsquery('english', $1)` to parse the query safely.
- Returns rows ordered by `ts_rank(search_vector, query_vector) DESC`.
- Returns `{ id, title, body_excerpt, rank }` — body_excerpt via `ts_headline`.
- Uses parameterized queries only — no string interpolation.
- Create a Server Action `src/lib/actions/search.ts` that calls `searchPosts` and returns results.
- Create `src/components/SearchBox.tsx` (Client Component) with a debounced input (300 ms) that
calls the Server Action via `useTransition` and renders results.
Do not install pg_search, Meilisearch, or any search service. Stop and list files before coding.

Notes d’implémentation

  • websearch_to_tsquery est plus sûr que to_tsquery pour les entrées utilisateur car il tolère les requêtes malformées (opérateurs manquants, caractères spéciaux) sans générer d’erreur PostgreSQL.
  • La colonne tsvector générée est automatiquement mise à jour lors des INSERT/UPDATE — aucun déclencheur nécessaire.
  • ts_headline nécessite le texte de la colonne d’origine et le vecteur de requête ; transmettez les deux depuis le SELECT.
  • L’index GIN rend la recherche rapide sur les grandes tables ; sans lui, les requêtes effectuent un balayage séquentiel.

Modifications de fichiers attendues

migrations/0010_add_fts.sql (new)
src/lib/search.ts (new)
src/lib/actions/search.ts (new — Server Action)
src/components/SearchBox.tsx (new — Client Component)

Critères d’acceptation

  • psql -f migrations/0010_add_fts.sql s’exécute sans erreur sur le schéma existant.
  • La recherche d’un mot qui n’apparaît que dans title renvoie le bon article.
  • La recherche d’une phrase avec une faute de frappe (ex. “postgress”) ne renvoie aucun résultat sans planter.
  • Les résultats sont classés avec les articles les plus pertinents en premier.

Commandes de test

Terminal window
psql "$DATABASE_URL" -f migrations/0010_add_fts.sql
bun run typecheck
bun run dev
# type a search term in SearchBox and verify ranked results appear
psql "$DATABASE_URL" -c "EXPLAIN ANALYZE SELECT * FROM posts WHERE search_vector @@ websearch_to_tsquery('english','test');"
# confirm "Index Scan using posts_search_idx" appears in output

Erreurs courantes de l’IA

  • Utiliser LIKE '%query%' au lieu de l’opérateur plein texte @@.
  • Utiliser to_tsquery('english', $1) avec des entrées utilisateur brutes — se casse sur des requêtes comme "foo bar".
  • Oublier l’index GIN, laissant la recherche en balayage séquentiel.
  • Appeler searchPosts dans un composant client au lieu de l’envelopper dans une action serveur.

Correctif du prompt

Fix Prompt
The search is using LIKE or crashing on special characters. Fix in order:
1. Replace any LIKE clause with `search_vector @@ websearch_to_tsquery('english', $1)`.
2. If `to_tsquery` is used directly with user input, replace it with `websearch_to_tsquery`.
3. Confirm the GIN index exists: `CREATE INDEX IF NOT EXISTS posts_search_idx ON posts USING GIN (search_vector);`
Show only the corrected diff. Do not modify unrelated files.