{
  "id": "add-postgres-full-text-search",
  "type": "prompts",
  "category": "prompts",
  "locale": "de",
  "url": "/de/prompts/add-postgres-full-text-search",
  "title": "Prompt zum Hinzufügen einer PostgreSQL-Volltextsuche",
  "description": "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.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Next.js",
    "PostgreSQL",
    "TypeScript"
  ],
  "tags": [
    "postgres",
    "sql",
    "search",
    "nextjs",
    "typescript"
  ],
  "difficulty": "medium",
  "updated": "2026-06-08",
  "markdown": "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.\n\n## Haupt-Prompt\n\n```txt title=\"Main Prompt\"\nYou are working in a Next.js App Router project with TypeScript and PostgreSQL (using the\n`postgres` npm package, not Prisma or Drizzle).\n\nTask: add full-text search over the `posts` table (columns: id, title, body, created_at).\n\nDatabase changes:\n1. Write a migration file `migrations/0010_add_fts.sql` that:\n   - Adds a generated column: `search_vector tsvector GENERATED ALWAYS AS\n     (to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,''))) STORED;`\n   - Creates a GIN index: `CREATE INDEX posts_search_idx ON posts USING GIN (search_vector);`\n2. Do NOT use `pg_trgm` or LIKE queries — use `@@` with `to_tsquery` or `websearch_to_tsquery`.\n\nApplication changes:\n- Create `src/lib/search.ts` with a `searchPosts(query: string, limit = 20)` function that:\n  - Uses `websearch_to_tsquery('english', $1)` to parse the query safely.\n  - Returns rows ordered by `ts_rank(search_vector, query_vector) DESC`.\n  - Returns `{ id, title, body_excerpt, rank }` — body_excerpt via `ts_headline`.\n  - Uses parameterized queries only — no string interpolation.\n- Create a Server Action `src/lib/actions/search.ts` that calls `searchPosts` and returns results.\n- Create `src/components/SearchBox.tsx` (Client Component) with a debounced input (300 ms) that\n  calls the Server Action via `useTransition` and renders results.\n\nDo not install pg_search, Meilisearch, or any search service. Stop and list files before coding.\n```\n\n## Implementierungshinweise\n\n- `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.\n- Die generierte `tsvector`-Spalte wird bei INSERT/UPDATE automatisch aktualisiert – es werden keine Trigger benötigt.\n- `ts_headline` benötigt den ursprünglichen Spaltentext und den Abfragevektor; übergeben Sie beide aus dem SELECT.\n- Der GIN-Index macht die Suche auf großen Tabellen schnell; ohne ihn werden Abfragen einen sequentiellen Scan durchführen.\n\n## Erwartete Dateiänderungen\n\n```txt\nmigrations/0010_add_fts.sql              (new)\nsrc/lib/search.ts                        (new)\nsrc/lib/actions/search.ts               (new — Server Action)\nsrc/components/SearchBox.tsx            (new — Client Component)\n```\n\n## Abnahmekriterien\n\n- `psql -f migrations/0010_add_fts.sql` läuft fehlerfrei auf dem vorhandenen Schema.\n- Die Suche nach einem Wort, das nur in `title` vorkommt, gibt den richtigen Beitrag zurück.\n- Die Suche nach einem Satz mit einem Tippfehler (z.B. \"postgress\") gibt keine Ergebnisse zurück, ohne abzustürzen.\n- Ergebnisse werden mit höherer Relevanz zuerst sortiert.\n\n## Testbefehle\n\n```bash\npsql \"$DATABASE_URL\" -f migrations/0010_add_fts.sql\nbun run typecheck\nbun run dev\n# type a search term in SearchBox and verify ranked results appear\npsql \"$DATABASE_URL\" -c \"EXPLAIN ANALYZE SELECT * FROM posts WHERE search_vector @@ websearch_to_tsquery('english','test');\"\n# confirm \"Index Scan using posts_search_idx\" appears in output\n```\n\n## Häufige KI-Fehler\n\n- Verwendung von `LIKE '%query%'` anstelle des `@@`-Volltextoperators.\n- Verwendung von `to_tsquery('english', $1)` mit rohen Benutzereingaben – bricht bei Abfragen wie `\"foo bar\"`.\n- Vergessen des GIN-Index, wodurch die Suche als sequentieller Scan verbleibt.\n- Aufruf von `searchPosts` in einer Client-Komponente, anstatt es in eine Server-Aktion zu verpacken.\n\n## Prompt zur Fehlerbehebung\n\n```txt title=\"Fix Prompt\"\nThe search is using LIKE or crashing on special characters. Fix in order:\n1. Replace any LIKE clause with `search_vector @@ websearch_to_tsquery('english', $1)`.\n2. If `to_tsquery` is used directly with user input, replace it with `websearch_to_tsquery`.\n3. Confirm the GIN index exists: `CREATE INDEX IF NOT EXISTS posts_search_idx ON posts USING GIN (search_vector);`\nShow only the corrected diff. Do not modify unrelated files.\n```"
}