Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як ранжувати результати пошуку й підсвічувати збіги?

Ранжування - ts_rank (за частотою слів запиту) або ts_rank_cd (ще й за близькістю слів одне до одного):

SELECT id, title,
       ts_rank(search, query) AS rank
FROM posts, websearch_to_tsquery('english', 'queue retries') AS query
WHERE search @@ query
ORDER BY rank DESC
LIMIT 20;

Ваги частин документа. setweight позначає частини літерами A-D (за спаданням важливості). Збіг у заголовку (A) важить більше, ніж у тексті (D):

setweight(to_tsvector('english', title), 'A') ||
setweight(to_tsvector('english', summary), 'B') ||
setweight(to_tsvector('english', body), 'D')

Ваги можна змінити в самому ts_rank: ts_rank('{0.1, 0.2, 0.4, 1.0}', search, query) - масив для D, C, B, A.

Нормалізація за довжиною: без неї довгий документ має перевагу просто тому, що містить більше слів. Третій аргумент ts_rank задає нормалізацію: ts_rank(search, query, 32) - ділити на (1 + rank) - чи 1 - на логарифм довжини документа.

Підсвічування збігів - ts_headline повертає фрагмент тексту з позначеними словами:

SELECT ts_headline('english', body, query,
       'StartSel=<mark>, StopSel=</mark>, MaxWords=35, MinWords=15, MaxFragments=2')
FROM posts, websearch_to_tsquery('english', 'queue retries') AS query
WHERE search @@ query;

Нюанси продуктивності:

  • ts_rank обчислюється для кожного збігу - на запиті з сотнями тисяч збігів сортування за рангом повільне. Індекс прискорює лише пошук, не ранжування.
  • ts_headline повільна: вона розбирає сирий текст заново. Викликайте її лише для рядків поточної сторінки - у зовнішньому запиті після LIMIT.
  • Екранування: ts_headline повертає текст разом з вашими мітками; якщо текст містить HTML від користувачів, його треба екранувати до підсвічування, інакше вийде XSS.

Коли ранжування PostgreSQL замало - урахування популярності, свіжості, персоналізації, «можливо, ви мали на увазі» - це вже задача пошукового рушія (Meilisearch, Elasticsearch, Typesense).

Докладніше в документації: Керування повнотекстовим пошуком

Схожі питання