intermediate

Full-text search

Используйте tsvector, dictionaries, ranking и GIN indexes, когда PostgreSQL search достаточен до search cluster.

Полнотекстовый поиск PostgreSQL токенизирует текст в `tsvector`, сопоставляет через `tsquery`, ранжирует через `ts_rank`. Подходит для product search умеренного масштаба, пока не оправдан Elasticsearch.

					ALTER TABLE articles ADD COLUMN search_vector tsvector
  GENERATED ALWAYS AS (
    setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
    setweight(to_tsvector('english', coalesce(body, '')), 'B')
  ) STORED;

CREATE INDEX idx_articles_fts ON articles USING GIN (search_vector);

SELECT id, title, ts_rank(search_vector, query) AS rank
FROM articles, plainto_tsquery('english', 'postgres indexing') AS query
WHERE search_vector @@ query
ORDER BY rank DESC
LIMIT 20;
				

Словари задают стемминг и стоп-слова. Префикс — `:*` в tsquery или trigram (`pg_trgm`) для fuzzy. Подсветка — `ts_headline`.

На интервью: pipeline tsvector + GIN; когда FTS достаточно vs отдельный search cluster; как веса влияют на релевантность.

Типовые ошибки: поиск по сырому тексту без индекса; неверный language config; ожидание typo tolerance уровня Google от базового FTS; вектор не обновляется при записи (generated columns или triggers).

Компромисс — простота эксплуатации в PostgreSQL против продвинутой релевантности, анализаторов и горизонтального масштаба search engine.

Чеклист:

  • Храните или генерируйте tsvector при записи.
  • Индекс GIN (или GiST с другим trade-off).
  • Словарь/язык под тип контента.
  • Запасной план, если recall или масштаб не хватает.