P PasteCode
提示词

添加 PostgreSQL 全文搜索的提示

复制粘贴 AI 提示,为现有 Next.js 应用添加原生 PostgreSQL 全文搜索,使用 tsvector、GIN 索引和排序结果。

CursorClaude CodeCodexWindsurf Next.jsPostgreSQLTypeScript
.md .json 难度: 中等 更新于 2026年6月8日

使用此提示为现有应用添加真正的 PostgreSQL 全文搜索——使用 tsvector、GIN 索引和 ts_rank,而无需代理转向 Elasticsearch、Algolia 或第三方搜索 API。

主要提示

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.

实施说明

  • websearch_to_tsqueryto_tsquery 更安全,因为它能容忍格式错误的查询(缺少运算符、特殊字符),而不会抛出 PostgreSQL 错误。
  • 生成的 tsvector 列会在 INSERT/UPDATE 时自动更新——无需触发器。
  • ts_headline 需要原始列文本和查询向量;从 SELECT 中同时传递两者。
  • GIN 索引使大表上的搜索速度更快;没有它,查询将进行顺序扫描。

预期文件更改

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)

验收标准

  • psql -f migrations/0010_add_fts.sql 在现有架构上运行无错误。
  • 搜索仅出现在 title 中的单词会返回正确的文章。
  • 搜索带有拼写错误的短语(例如 “postgress”)不会返回结果,也不会崩溃。
  • 结果按相关性排序,相关性高的文章优先。

测试命令

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

常见 AI 错误

  • 使用 LIKE '%query%' 而不是 @@ 全文运算符。
  • 使用 to_tsquery('english', $1) 处理原始用户输入——会在像 "foo bar" 这样的查询上出错。
  • 忘记 GIN 索引,导致搜索变成顺序扫描。
  • 在客户端组件中调用 searchPosts,而不是将其包装在 Server Action 中。

修复提示

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.