Перейти к содержимому

Живой поиск с подсказками - выдача, доступность, подстроки

Делаем подсказки в поиске по сайту: компонент, чистая выдача, поиск по части слова и своевременная переиндексация.

Решение

Ставим компонент подсказок:

$APPLICATION->IncludeComponent('bitrix:search.title', '', [
'CATEGORY_0' => ['iblock_catalog'], // где искать: тип инфоблока
'CATEGORY_0_iblock_catalog' => [$iblockId], // и конкретный инфоблок
'SHOW_INPUT' => 'Y', 'TOP_COUNT' => 5,
'CHECK_DATES' => 'Y', // снятое с публикации не показывать
]);

Категории поиска ограничивают выдачу нужным разделом. Без них подсказки приносят новости, служебные страницы и элементы соседних инфоблоков, и покупатель видит случайный набор ссылок вместо товаров.

Убираем недоступные товары из индекса:

use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler('search', 'BeforeIndex',
static function ($fields) { // массив приходит по значению
if ($fields['MODULE_ID'] === 'iblock' && !isAvailable($fields['ITEM_ID'])) {
unset($fields['BODY']); // так запись исключается из индекса
}
return $fields; // обработчик обязан вернуть массив
});

Компонент подсказок не проверяет доступность товара сам. Он показывает то, что лежит в индексе, поэтому товары без цены и снятые с продажи убирают на этапе индексации, а не в шаблоне выдачи.

Обработчик принимает массив по значению и обязан его вернуть. Ссылка в сигнатуре здесь ошибка: правки уедут в никуда, а элемент попадёт в индекс без изменений.

Обработчик индексации - единственное место, где такую чистку делают дёшево. Правка шаблона выдачи не помогает: компонент уже посчитал количество найденного, и страница «показать всё» останется пустой при непустых подсказках.

Добавляем свои поисковые фразы:

$prop = new CIBlockProperty();
$prop->Add(['IBLOCK_ID' => $iblockId, 'CODE' => 'SEARCH_WORDS',
'NAME' => 'Поисковые фразы', 'PROPERTY_TYPE' => 'S',
'SEARCHABLE' => 'Y']); // значения свойства участвуют в поиске
// в свойство кладут синонимы и обиходные названия: «термокольцо», «кольцо»

Подсказки ищут только по заголовкам элементов, и это не настраивается. Полный поиск по описаниям и свойствам делает страница результатов, а подсказки остаются быстрым поиском по названиям.

Второе ограничение - поиск по началу слова, а не по любой его части. Запрос «ильник» не найдёт светильник никогда, и лечится это списком синонимов в отдельном свойстве или внешним поисковым движком.

Синонимы в свойстве решают и вторую задачу - народные названия. Покупатель ищет «зарядку» вместо «блока питания», и список таких слов в отдельном поле работает лучше любой настройки морфологии.

Пересобираем индекс после массовых правок:

\Bitrix\Main\Loader::includeModule('search');
CSearch::ReIndexAll(false, 30); // порциями по 30 секунд, чтобы не упереться в предел
// при обычном сохранении элемента индекс обновляется сам, при массовой правке - нет

Делаем подсказки по своим данным без модуля поиска:

$rs = CIBlockElement::GetList(['SORT' => 'ASC'],
['IBLOCK_ID' => $iblockId, 'ACTIVE' => 'Y', '%NAME' => $query],
false, ['nTopCount' => 10], ['ID', 'NAME', 'DETAIL_PAGE_URL']);
// поиск по части названия: медленнее индекса, но ищет по середине слова
// такой ответ отдают своим ajax-действием, а не отдельным файлом в корне

Свой поиск по названию оправдан там, где элементов немного и нужна именно подстрока. На каталоге в десятки тысяч позиций он проигрывает индексу по скорости, и тогда возвращаются к модулю поиска с синонимами.

Типичные проблемы

В подсказках появляются неактивные товары и товары без цены.

Компонент подсказок не проверяет доступность и показывает содержимое индекса. Недоступные записи убирают обработчиком события прямо на этапе их попадания в индекс.

Поиск по части слова ничего не находит.

Подсказки ищут по началу слова и только по заголовкам элементов. Синонимы кладут в отдельное свойство инфоблока либо ставят внешний поисковый движок целиком.

После обмена подсказки показывают старые названия.

Массовая запись элементов не обновляет индекс поиска сама по себе, в отличие от ручного сохранения. После крупных правок и обмена с учётной системой запускают полную переиндексацию.

В подсказках попадаются служебные страницы.

Категории поиска в параметрах компонента не ограничены нужным инфоблоком каталога товаров сайта. Область поиска задают параметрами компонента, а не фильтрацией в шаблоне выдачи.

Запрос подсказок отвечает ошибкой пятисотой.

Шаблон подсказок переверстан или его обработчик правился под другую версию самого продукта. Ошибку в этом случае ищут в журнале сервера, а не в настройках компонента.

Частые вопросы

Почему подсказки показывают недоступные товары?

Компонент отдаёт содержимое поискового индекса и доступность не проверяет - это его известное поведение. Недоступные позиции исключают из индекса обработчиком события индексации.

Как научить поиск находить по середине слова?

Штатный индекс так не умеет: он ищет по началу слова, а подсказки - ещё и только по заголовкам. Обычно заводят свойство с синонимами и обиходными названиями, а при серьёзных требованиях ставят внешний поисковый движок.

Когда нужна переиндексация?

После массовых правок, обмена с учётной системой и изменения списка индексируемых свойств. При обычном сохранении элемента в админке индекс обновляется сам.

Делать подсказки своим кодом или компонентом?

Компонентом, если поиск идёт по каталогу и нужен нормальный индекс. Своим ajax-действием - если данных немного и требуется поиск по произвольной подстроке.

Почему в подсказках нет части товаров?

Либо они не попали в индекс, либо их отсекли категории поиска в параметрах компонента. Проверяют оба условия: сначала наличие записи в индексе, потом настройки области поиска.

Смежное

Первоисточник