Skip to main content

Для чого використовується пошук?

Коротка відповідь

Пошук використовується для швидкого і точного знаходження потрібних даних серед великих обсягів інформації. Він поліпшує користувацький досвід, підвищує конверсію, пришвидшує роботу з продуктом, допомагає аналізувати дані та ухвалювати рішення, а також знижує навантаження на підтримку.

Детальна відповідь

Основні цілі пошуку

  • Швидкий доступ до даних: знаходити документи, товари, користувачів, логи, метрики.
  • Навігація та discovery: допомогти користувачу зрозуміти асортимент і структуру контенту.
  • Аналітика та моніторинг: оперативно знаходити аномалії та інциденти в потоках подій і логах.
  • Автоматизація: знаходити сутності у фонових задачах, тригерах, інтеграціях.
  • Персоналізація та рекомендації: враховувати інтереси користувача при видачі й ранжуванні результатів.
  • Зниження навантаження на підтримку: користувачі самі знаходять відповіді та контент.

Види пошуку

  • Точний збіг: за ключем/ID/полем.
  • Підрядковий: LIKE/ILIKE, префіксний пошук, автодоповнення.
  • Повнотекстовий: за словами, з урахуванням морфології та релевантності.
  • Фразовий: "пошук за точною фразою" з порядком слів.
  • Фільтраційний/фасетний: поля-грані (категорія, ціна), агрегації.
  • Нечіткий (fuzzy): з урахуванням описок (відстань Левенштейна, BK-дерева).
  • Синоніми та нормалізація: врахування форм слова та альтернативних термінів.
  • Геопошук: за координатами і радіусом, сортування за відстанню.
  • Векторний/семантичний: пошук за змістом з ембеддингами.

Як це працює під капотом

  • Індексація: токенізація, нормалізація, стоп-слова, стемінг/лематизація, n-грами; побудова інвертованого індексу.
  • Структури даних: хеш-таблиці, B-/B+ дерева, Trie, інвертований індекс, BK-дерево.
  • Релевантність і ранжування: TF-IDF, BM25, буст важливих полів, свіжість, популярність, персоналізація.
  • Обробка запитів: парсинг операторів (AND/OR/NOT), фільтри, сортування, пагінація, підсвічування збігів, фасети.
  • Архітектура: окремий рушій (спеціалізовані системи) або вбудований FTS у БД; асинхронна індексація з черг; eventual consistency; шардування, реплікація; кешування.

UX-практики

  • Автодоповнення і підказки (suggestions), популярні запити.
  • Дебаунс уведення і скасування застарілих запитів, стан завантаження і порожні стани.
  • Підсвічування збігів, синоніми, виправлення описок, "можливо, ви мали на увазі".
  • Фільтри, фасети, збережені запити, історія пошуку, гарячі клавіші.

Метрики якості

  • Precision / Recall, F1 - точність і повнота.
  • MRR, NDCG - якість ранжування.
  • CTR, конверсія після кліку, час до першого результату, швидкість відповіді.

Продуктивність і масштабування

  • Індекси в БД: GIN/GIST для повнотексту, btree для точних збігів, покривні індекси.
  • Кешування: відповідей, підказок, фасетів; прогрів та інвалідація.
  • Пагінація: keyset замість OFFSET/LIMIT на великих даних, таймаути запитів.
  • Асинхронна індексація, контроль відставання індексу, планові реіндексації та бекапи.

Безпека та відповідність

  • Фільтрація за правами доступу (row-level security), багатоорендність (tenant_id).
  • Маскування і мінімізація PII, аудит запитів, rate limiting.

Інтернаціоналізація

  • Unicode-сумісність, коректна колація і регістронезалежність.
  • Морфологія для різних мов, транслітерація (наприклад, укр/лат).

Приклади коду

SQL: повнотекстовий пошук у Postgres

-- Створення індексу повнотекстового пошуку за колонками title і body CREATE INDEX idx_posts_fts ON posts USING GIN ( to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')) ); -- Пошук з урахуванням морфології (plainto_tsquery зручний для користувацького вводу) SELECT id, title, ts_headline('english', body, plainto_tsquery('english', $1)) AS snippet, ts_rank_cd( to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')), plainto_tsquery('english', $1) ) AS rank FROM posts WHERE to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')) @@ plainto_tsquery('english', $1) ORDER BY rank DESC LIMIT 20 OFFSET $2; -- Приклад simple LIKE (підрядковий пошук; менш ефективний) SELECT id, title FROM posts WHERE title ILIKE '%' || $1 || '%' LIMIT 20;

Backend: Node.js Express endpoint з пагінацією і фільтрами

import express from 'express'; import { Pool } from 'pg'; const app = express(); const pool = new Pool({ connectionString: process.env.DATABASE_URL }); app.get('/search', async (req, res) => { const q = String(req.query.q || '').trim(); const limit = Math.min(parseInt(String(req.query.limit || '20'), 10), 100); const cursor = req.query.cursor ? Number(req.query.cursor) : null; // keyset пагінація const category = req.query.category ? String(req.query.category) : null; const params = [] as any[]; let where = [] as string[]; if (q) { params.push(q); where.push("to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')) @@ plainto_tsquery('english', $" + params.length + ")"); } if (category) { params.push(category); where.push('category = $' + params.length); } if (cursor) { params.push(cursor); where.push('id > $' + params.length); // keyset: сортування за id ASC } const sql = ` SELECT id, title, ts_rank_cd( to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')), COALESCE(plainto_tsquery('english', $1), to_tsquery('english', '')) ) AS rank FROM posts ${where.length ? 'WHERE ' + where.join(' AND ') : ''} ORDER BY id ASC LIMIT ${limit + 1} `; try { const { rows } = await pool.query(sql, params); const hasMore = rows.length > limit; const items = hasMore ? rows.slice(0, limit) : rows; res.json({ items, nextCursor: hasMore ? items[items.length - 1].id : null }); } catch (e) { res.status(500).json({ error: 'search_failed' }); } }); app.listen(3000);

Frontend: React, дебаунс і скасування застарілих запитів

import { useEffect, useMemo, useState } from 'react'; function useDebouncedValue(value, delay = 300) { const [debounced, setDebounced] = useState(value); useEffect(() => { const id = setTimeout(() => setDebounced(value), delay); return () => clearTimeout(id); }, [value, delay]); return debounced; } export default function SearchBox() { const [q, setQ] = useState(''); const debouncedQ = useDebouncedValue(q, 300); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const controller = useMemo(() => new AbortController(), [debouncedQ]); useEffect(() => { if (!debouncedQ) { setItems([]); return; } setLoading(true); setError(null); fetch(`/search?q=${encodeURIComponent(debouncedQ)}`, { signal: controller.signal }) .then(r => { if (!r.ok) throw new Error('Network error'); return r.json(); }) .then(data => setItems(data.items || [])) .catch(err => { if (err.name !== 'AbortError') setError(err.message); }) .finally(() => setLoading(false)); return () => controller.abort(); }, [debouncedQ]); return ( <div> <input placeholder="Пошук..." value={q} onChange={e => setQ(e.target.value)} /> {loading && <div>Завантаження...</div>} {error && <div>Помилка: {error}</div>} {!loading && !error && items.length === 0 && debouncedQ && <div>Нічого не знайдено</div>} <ul> {items.map(i => <li key={i.id}>{i.title}</li>)} </ul> </div> ); }

Алгоритмічний аспект: бінарний пошук

function binarySearch(arr, x) { let l = 0, r = arr.length - 1; while (l <= r) { const m = l + ((r - l) >> 1); if (arr[m] === x) return m; if (arr[m] < x) l = m + 1; else r = m - 1; } return -1; } // Використання: масив має бути відсортований console.log(binarySearch([1,3,5,7,9], 7)); // 3

Чек-лист впровадження пошуку

  1. Зібрати вимоги: типи контенту, поля, мова, навантаження, SLA.
  2. Обрати технологію: БД з FTS або спеціалізований рушій; оцінити вартість і підтримку.
  3. Схема даних та індекси: які поля індексуються, морфологія, синоніми, токенізація.
  4. Пайплайн індексації: джерела, черги, дедуплікація, оновлення, контроль відставання.
  5. API: фільтри, сортування, пагінація, підсвічування, безпека на рівні запитів.
  6. UI/UX: підказки, автодоповнення, фасети, порожні стани, доступність (a11y).
  7. Спостережуваність: логування запитів, метрики, трейсинг, дашборди, алерти.
  8. Якість і релевантність: офлайн/онлайн оцінки, A/B-тести, збір кліків для навчання.
  9. Експлуатація: бекапи, реіндексація без даунтайму, шардування/реплікація, план оновлень.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.