P PasteCode
Prompt

Prompt zum Hinzufügen einer PostgreSQL-Volltextsuche

KI-Prompt zum Kopieren und Einfügen, um native PostgreSQL-Volltextsuche mit tsvector, GIN-Index und bewerteten Ergebnissen zu einer bestehenden Next.js-App hinzuzufügen.

CursorClaude CodeCodexWindsurf Next.jsPostgreSQLTypeScript
.md .json Schwierigkeit: Mittel Aktualisiert 8. Juni 2026

Verwenden Sie diesen Prompt, um eine echte PostgreSQL-Volltextsuche zu einer bestehenden App hinzuzufügen – mit tsvector, einem GIN-Index und ts_rank – ohne dass der Agent auf Elasticsearch, Algolia oder eine Drittanbieter-Such-API zurückgreift.

Haupt-Prompt

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.

Implementierungshinweise

  • websearch_to_tsquery ist sicherer als to_tsquery für Benutzereingaben, da es fehlerhafte Abfragen (fehlende Operatoren, Sonderzeichen) toleriert, ohne einen PostgreSQL-Fehler auszulösen.
  • Die generierte tsvector-Spalte wird bei INSERT/UPDATE automatisch aktualisiert – es werden keine Trigger benötigt.
  • ts_headline benötigt den ursprünglichen Spaltentext und den Abfragevektor; übergeben Sie beide aus dem SELECT.
  • Der GIN-Index macht die Suche auf großen Tabellen schnell; ohne ihn werden Abfragen einen sequentiellen Scan durchführen.

Erwartete Dateiänderungen

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)

Abnahmekriterien

  • psql -f migrations/0010_add_fts.sql läuft fehlerfrei auf dem vorhandenen Schema.
  • Die Suche nach einem Wort, das nur in title vorkommt, gibt den richtigen Beitrag zurück.
  • Die Suche nach einem Satz mit einem Tippfehler (z.B. “postgress”) gibt keine Ergebnisse zurück, ohne abzustürzen.
  • Ergebnisse werden mit höherer Relevanz zuerst sortiert.

Testbefehle

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

Häufige KI-Fehler

  • Verwendung von LIKE '%query%' anstelle des @@-Volltextoperators.
  • Verwendung von to_tsquery('english', $1) mit rohen Benutzereingaben – bricht bei Abfragen wie "foo bar".
  • Vergessen des GIN-Index, wodurch die Suche als sequentieller Scan verbleibt.
  • Aufruf von searchPosts in einer Client-Komponente, anstatt es in eine Server-Aktion zu verpacken.

Prompt zur Fehlerbehebung

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.