Разработка модуля поиска по каталогу 1С-Битрикс
Штатный поиск Битрикс (search.php и модуль search) — полнотекстовый индекс по таблице b_search_content. Он работает приемлемо для контентных сайтов, но плохо справляется с задачами каталога: не понимает транслитерацию, не учитывает синонимы, не умеет «iphone 12» найти по запросу «айфон 12», не поддерживает поиск по числовым диапазонам («наушники до 3000 рублей»). Как только каталог превышает 5 000–10 000 позиций и конкуренты выигрывают по релевантности — нужен собственный поисковый модуль.
Варианты реализации
Прежде чем писать собственный индекс, стоит честно рассмотреть готовые решения:
Elasticsearch / OpenSearch. Отдельный сервис с богатым DSL, поддержкой фасетного поиска, нечёткого поиска, подсветки найденного. Требует отдельного сервера (или managed-сервиса), умения администрировать. Оптимален для каталогов от 50 000 позиций с высокой нагрузкой.
PostgreSQL full-text search. Встроен в БД, не требует дополнительной инфраструктуры, поддерживает русский и английский через конфигурации (russian, english). Подходит для каталогов до 100 000 позиций при разумной нагрузке. Именно этот вариант часто выбирается для Битрикс-проектов как оптимальный компромисс.
Sphinx / Manticore Search. Высокая скорость на больших объёмах, хорошая русскоязычная морфология. Требует отдельного процесса и периодической переиндексации.
Модуль проектируется с абстрактным слоем поискового движка, чтобы можно было переключить бэкенд без переработки логики Битрикс.
Архитектура модуля
Индексатор. Агент раз в час проверяет изменения в b_iblock_element (по полю TIMESTAMP_X) и обновляет поисковый индекс. При сохранении товара через события OnAfterIBlockElementUpdate индекс обновляется немедленно для этого элемента.
Индекс содержит поля: название, описание, характеристики (значения свойств), артикул, бренд, категория, цена (для фильтрации по диапазону), наличие. Числовые поля хранятся отдельно для range-запросов.
class SearchIndexer {
public function indexElement(int $elementId): void {
$element = $this->loadElementWithProps($elementId);
$document = [
'id' => $elementId,
'title' => $element['NAME'],
'description' => strip_tags($element['DETAIL_TEXT']),
'sku' => $element['PROPERTY_ARTICLE_VALUE'],
'price' => $this->getMinPrice($elementId),
'in_stock' => $this->isInStock($elementId),
'brand' => $element['PROPERTY_BRAND_VALUE'],
'tsvector' => null, // заполняется PostgreSQL автоматически
];
SearchIndexTable::merge($document);
}
}
Поисковый запрос. Пользовательская строка нормализуется: транслитерация (iphone → айфон и обратно), исправление раскладки клавиатуры (руьщт → iphone), удаление стоп-слов. После нормализации — запрос к индексу с ранжированием по ts_rank.
Поиск по синонимам. Словарь синонимов хранится в таблице myvendor_search_synonyms (пары «запрос → каноническая форма»). Перед поиском запрос проверяется на совпадение с синонимами.
Детально: нечёткий поиск и опечатки
Самая частая причина нулевых результатов поиска — опечатки. Решение — расстояние Дамерау-Левенштейна для коротких запросов (1–2 слова) и pg_trgm для PostgreSQL:
-- Индекс триграм для нечёткого поиска
CREATE INDEX idx_search_title_trgm
ON myvendor_search_index
USING gin(title gin_trgm_ops);
-- Нечёткий поиск с порогом схожести
SELECT id, title, similarity(title, 'айфно') AS sim
FROM myvendor_search_index
WHERE title % 'айфно'
ORDER BY sim DESC
LIMIT 20;
Расширение pg_trgm позволяет искать по схожести с порогом (например, 0.3) — это эффективнее, чем хранить предвычисленные исправления в словаре.
Саджест (автодополнение)
AJAX-эндпоинт возвращает подсказки по первым 2+ символам запроса. Подсказки берутся из предрассчитанной таблицы популярных запросов (myvendor_search_popular, обновляется из лога запросов раз в сутки) и из индекса по LIKE 'запрос%' с лимитом 5. Ответ кешируется в Memcached/Redis по ключу запроса с TTL 1 час.
Сроки разработки
| Масштаб | Состав | Срок |
|---|---|---|
| Базовый | PostgreSQL FTS + нормализация + саджест | 3–4 недели |
| Средний | + нечёткий поиск + синонимы + фасеты в результатах | 5–7 недель |
| Расширенный | + Elasticsearch + персонализация + аналитика запросов | 9–12 недель |
Перед разработкой стоит собрать реальный лог поисковых запросов с сайта — он покажет, какие запросы не дают результатов сейчас и какие синонимы нужны в первую очередь.







