Налаштування Elasticsearch для веб-додатків

**Elasticsearch краще ніж PostgreSQL для повнотекстового пошуку: він швидший у 10–20 разів і має потужні можливості фасетів та автодоповнення.** Ми маємо 5+ років досвіду та 30+ успішних проєктів з налаштування Elasticsearch. Elasticsearch лучше PostgreSQL в 10–20 разів за швидкістю пошуку.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Налаштування Elasticsearch для веб-додатків
Складний
~2-3 дні

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1419
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    983
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1245
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    998

Elasticsearch краще ніж PostgreSQL для повнотекстового пошуку: він швидший у 10–20 разів і має потужні можливості фасетів та автодоповнення. Ми маємо 5+ років досвіду та 30+ успішних проєктів з налаштування Elasticsearch. Elasticsearch лучше PostgreSQL в 10–20 разів за швидкістю пошуку.

Уявіть: ваш інтернет-магазин виріс до 500 000 товарів, і пошук за назвою через ILIKE % в PostgreSQL гальмує на кожній літері. Клієнти йдуть, конверсія падає — кожна секунда затримки знижує її на 7%. Ми з такою ситуацією стикалися не раз. В одному проєкті пошук по 1 млн товарів займав 8 секунд, після міграції на Elasticsearch — 80 мс. Конверсія зросла на 15%. За час роботи ми налаштували Elasticsearch для 30+ проєктів — від каталогів до маркетплейсів. Наш досвід показує: правильне налаштування індексів та аналізаторів скорочує час пошуку в 10 разів.

Чому Elasticsearch, а не повнотекстовий пошук у PostgreSQL?

PostgreSQL вміє повнотекстовий пошук через tsvector, але він не справляється з високими навантаженнями, складною морфологією та фасетами. Індексування даних у Elasticsearch виконується через мапінги, що задають структуру. Пошуковий двигун Elasticsearch забезпечує швидкий повнотекстовий пошук. Фасетний пошук дозволяє фільтрувати результати за категоріями, цінами тощо. Синхронізація Elasticsearch з PostgreSQL реалізується через логічну реплікацію. Порівняємо:

Критерій PostgreSQL (ILIKE/tsvector) Elasticsearch
Швидкість пошуку по 1 млн записів 200–500 мс 10–50 мс
Морфологія української мови Базова через словники Стемінг, синоніми, кастомні аналізатори
Фасетна фільтрація Обмежена Потужні агрегації
Автодоповнення Костели з триграмами Edge n-gram, Suggester
Геопошук Через PostGIS, повільно Нативно, швидко

Крім того, розподілений пошук Elasticsearch дозволяє обробляти мільярди документів.

Як ми налаштовуємо Elasticsearch під вашу задачу

Ми не ставимо Elasticsearch «з коробки». Завжди аналізуємо структуру даних і типові запити. Ось реальний приклад: для каталогу електроніки з 200 000 товарів ми створили індекс з двома аналізаторами: українським (стемінг + стоп-слова) та автодоповненням (edge n-gram). Налаштування зайняло 4 дні. В іншому проєкті знадобився кастомний char_filter для очищення назв від спецсимволів.

Встановлення Elasticsearch 8.x

# Додати репозиторій wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list apt update && apt install -y elasticsearch # Зберегти пароль superuser з виводу встановлення systemctl enable elasticsearch && systemctl start elasticsearch 

Мінімальний конфіг для single-node dev:

# /etc/elasticsearch/elasticsearch.yml cluster.name: myapp-search node.name: node-1 path.data: /var/lib/elasticsearch path.logs: /var/log/elasticsearch network.host: 127.0.0.1 discovery.type: single-node xpack.security.enabled: true xpack.security.http.ssl.enabled: false # для dev; в prod — увімкнути 

Heap виділяємо так: не більше 50% RAM, не більше 32 ГБ (через compressed OOP). Для старту 4 ГБ достатньо.

Мапінг індексу

Мапінг — схема індексу. Неправильний мапінг не виправити без переіндексації. Докладніше читайте в мапінг Elasticsearch:

PUT /products { "settings": { "number_of_shards": 2, "number_of_replicas": 1, "analysis": { "analyzer": { "russian_analyzer": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "russian_stop", "russian_stemmer"] }, "autocomplete_analyzer": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "edge_ngram_filter"] }, "autocomplete_search": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase"] } }, "filter": { "russian_stop": { "type": "stop", "stopwords": "_russian_" }, "russian_stemmer": { "type": "stemmer", "language": "russian" }, "edge_ngram_filter": { "type": "edge_ngram", "min_gram": 2, "max_gram": 20 } } } }, "mappings": { "properties": { "id": { "type": "keyword" }, "name": { "type": "text", "analyzer": "russian_analyzer", "fields": { "autocomplete": { "type": "text", "analyzer": "autocomplete_analyzer", "search_analyzer": "autocomplete_search" }, "keyword": { "type": "keyword" } } }, "description": { "type": "text", "analyzer": "russian_analyzer" }, "category": { "type": "keyword" }, "brand": { "type": "keyword" }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "in_stock": { "type": "boolean" }, "attributes": { "type": "object", "dynamic": true }, "location": { "type": "geo_point" }, "created_at": { "type": "date" } } } } 

Пошуковий запит з фасетами

POST /products/_search { "query": { "bool": { "must": [ { "multi_match": { "query": "бездротові навушники", "fields": ["name^3", "description", "name.autocomplete^2"], "type": "best_fields", "fuzziness": "AUTO" } } ], "filter": [ { "term": { "in_stock": true } }, { "range": { "price": { "gte": 1000, "lte": 10000 } } }, { "terms": { "category": ["audio", "headphones"] } } ] } }, "aggs": { "categories": { "terms": { "field": "category", "size": 20 } }, "brands": { "terms": { "field": "brand", "size": 30 } }, "price_ranges": { "range": { "field": "price", "ranges": [ { "to": 1000 }, { "from": 1000, "to": 5000 }, { "from": 5000, "to": 15000 }, { "from": 15000 } ] } } }, "highlight": { "fields": { "name": {}, "description": { "fragment_size": 150 } } }, "from": 0, "size": 24, "sort": [{ "_score": "desc" }, { "created_at": "desc" }] } 

Як налаштувати автодоповнення?

Автодоповнення реалізується через edge n-gram аналізатор, як показано в мапінгу. Edge n-gram створює токени від 2 до 20 символів. Користувачі отримують підказки вже після введення 2–3 символів — це підвищує UX. Поле name.autocomplete індексує початок кожного слова. У пошуковому запиті використовуйте match_phrase_prefix або multi_match по цьому полю.

Орієнтовні терміни

Терміни залежать від складності. Базове налаштування з одним індексом та інтеграцією — 3–5 днів. Якщо потрібні автодоповнення, фасети та синхронізація з PostgreSQL — ще 3–5 днів. Кластер із 3 нод з моніторингом — 1–2 тижні. Вартість розраховується індивідуально. Нижче таблиця орієнтовних термінів по етапах:

Етап Тривалість
Аналітика та проєктування 1–2 дні
Встановлення та налаштування індексу 1–2 дні
Інтеграція з додатком 2–3 дні
Тестування та оптимізація 1–2 дні
Деплой та моніторинг 1 день

Синхронізація даних з PostgreSQL

Для синхронізації використовуємо логічну реплікацію через Debezium + Kafka у промислових сценаріях. Для старту підходить періодичний реіндекс через cron. Нижче приклад на TypeScript:

// sync/product-indexer.ts import { Client } from '@elastic/elasticsearch' import { Pool } from 'pg' const es = new Client({ node: 'http://localhost:9200', auth: { username: 'elastic', password: process.env.ES_PASSWORD! } }) const pg = new Pool({ connectionString: process.env.DATABASE_URL }) export async function indexProduct(id: string) { const { rows } = await pg.query(` SELECT p.*, c.name AS category_name, json_agg(json_build_object('key', a.key, 'value', a.value)) AS attributes FROM products p LEFT JOIN categories c ON c.id = p.category_id LEFT JOIN product_attributes a ON a.product_id = p.id WHERE p.id = $1 GROUP BY p.id, c.name `, [id]) if (!rows.length) { await es.delete({ index: 'products', id }) return } const p = rows[0] await es.index({ index: 'products', id: p.id, document: { id: p.id, name: p.name, description: p.description, category: p.category_name, price: p.price, in_stock: p.stock_quantity > 0, attributes: Object.fromEntries(p.attributes?.map((a: any) => [a.key, a.value]) ?? []), created_at: p.created_at } }) } export async function reindexAll() { const { rows } = await pg.query('SELECT id FROM products WHERE deleted_at IS NULL') const chunks = chunk(rows.map(r => r.id), 100) for (const ids of chunks) { await Promise.all(ids.map(indexProduct)) console.log(`Indexed ${ids.length} products`) } } 

Покроковий план налаштування

  1. Аналітика — вивчаємо структуру даних, типові запити, вимоги до швидкості (1–2 дні).
  2. Проєктування — розробляємо мапінг, аналізатори, схему синхронізації (1–2 дні).
  3. Реалізація — встановлюємо Elasticsearch, налаштовуємо індекс, пишемо інтеграцію (3–5 днів).
  4. Тестування — перевіряємо релевантність пошуку, фасети, швидкість (1–2 дні).
  5. Деплой — розгортаємо на production, налаштовуємо моніторинг (1 день).

Що входить у роботу

Після завершення робіт ви отримуєте:

  • Налаштований кластер Elasticsearch (одна нода або кластер) з доступом
  • Індекси з кастомними аналізаторами під українську мову (або російську за потреби)
  • Інтеграцію з вашим додатком через REST API
  • Скрипти синхронізації даних (наприклад, з PostgreSQL)
  • Документацію з експлуатації
  • Навчання вашої команди

Ми надаємо гарантію на 3 місяці: якщо пошук працює не так, як очікувалося, виправляємо безкоштовно.

Моніторинг кластера

Рекомендуємо відстежувати здоров'я кластера через _cluster/health та ввімкнути slowlog для пошукових запитів. Для збору метрик використовуйте Elastic Metricbeat — це дозволяє вчасно помітити деградацію.

Типові помилки при налаштуванні
  • Неправильний мапінг — dynamic mapping призводить до неочікуваних типів полів, що ламає фасети. Завжди задавайте схему явно.
  • Замалий heap — нестача пам'яті спричиняє часті GC паузи та падіння продуктивності. Виділяйте не менше 50% RAM, але не більше 32 ГБ.
  • Відсутність slowlog — без нього не побачити повільні запити. Увімкніть slowlog у конфігу: index.search.slowlog.threshold.query.warn: 2s.
  • Ігнорування реплік — для відмовостійкості потрібна хоча б 1 репліка. Налаштуйте number_of_replicas: 1.

Розпочати роботу

Якщо ваш пошук гальмує або не справляється з навантаженням — зв'яжіться з нами. Ми оцінимо вашу систему та запропонуємо рішення. Замовте налаштування Elasticsearch під ключ — отримайте консультацію безкоштовно. Не відкладайте: кожна секунда затримки коштує вам клієнтів. Замовте аудит сьогодні.