C.W.K.
Stream
Lesson 05 of 10 · published

Elasticsearch 없는 Full-Text Search

~14 min · extensions, fts

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

tsvector 와 tsquery

PostgreSQL 이 완전한 full-text search 엔진 ship. tsvector 가 정규화 + stem 된 lexeme 저장; tsquery 가 검색 쿼리 표현. 매치 연산자 @@ 가 tsvector 가 tsquery 매치하는지 테스트. GIN 인덱스 있으면 수백만 document 가로질러 ms 단위 검색.

구성 요소

  • to_tsvector('english', text) — 텍스트를 정규화 vector 로.
  • to_tsquery('english', 'postgres & performance') — 쿼리 파싱.
  • plainto_tsquery / websearch_to_tsquery — 친절한 쿼리 파서.
  • ts_rank / ts_rank_cd — relevance 점수.
  • ts_headline — 매치 term highlight 한 snippet 생성.

tsvector 저장

성능 위해, tsvector 를 generated column 으로 materialise + GIN 인덱스. write 시 변환 한 번 계산 → 모든 검색에 재사용.

Code

Full-text search 셋업·sql
CREATE TABLE articles (
    id        INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    title     TEXT NOT NULL,
    body      TEXT NOT NULL,
    tsv       tsvector GENERATED ALWAYS AS (
                to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,''))
              ) STORED,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX articles_tsv_gin ON articles USING gin (tsv);
Search + rank + snippet·sql
WITH q AS (SELECT websearch_to_tsquery('english', 'postgres performance') AS query)
SELECT id, title,
       ts_rank(tsv, q.query)                            AS score,
       ts_headline('english', body, q.query,
                   'StartSel=<mark>, StopSel=</mark>')   AS snippet
FROM   articles, q
WHERE  tsv @@ q.query
ORDER  BY score DESC
LIMIT  10;

External links

Exercise

TEXT 무거운 테이블에 generated tsvector 컬럼 + GIN 인덱스 추가. ranking + highlighted snippet 으로 full-text search 실행. naive ILIKE '%term%' 쿼리와 비교 — 속도 차이 관찰.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.