понедельник, 10 апреля 2017 г.

Поиск по нестандартным элементам

Сегодня, друзья, я расскажу вам о том, как добавить в стандартный битриксовый поиск возможность искать по нестандартным элементам.
Стандартный битриксовый поиск это тот который bitrix:search.page. А нестандартные элементы - это, например, веб-формы. Или вообще какой-нибудь контент, который вы в своем, лично вами разработанном модуле, храните в отдельной таблице в БД.

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

Немного покурим мануалы и найдем метод CSearch::Index. Его смысл прост - он добавит в таблицу поискового содержимого новую запись. Это, конечно, хорошо, но недостаток этого метода в том, что после переиндексации поиска все данные, внесенные через этот метод, успешно удалятся. Поэтому, пойдем дальше и найдем нужное событие. Это событие называется OnReIndex.

Как следует из его описания, данное событие наступает в момент переиндексации данных. Добавив свой обработчик события, мы заставим Битрикс индексировать и наши данные и добавлять их в таблицу поискового контента. Итак, делаем следующее:

// Обработчик при индексации данных поиска
AddEventHandler('search', 'OnReindex', ['My\Namespace\GoesHere', 'SearchReindex']);
// Или
RegisterModuleDependences("search", "OnReindex", "my_module", "My\Namespace\GoesHere", "SearchReindex");

// Собственно обработчик события
namespace My\Namespace\GoesHere;

class EventHandlers {

    function SearchReindex($NS, $oCallback, $callback_method)
    {
        /* Каким-либо образом получаем требуемый контент */
        $required_content = My\Namespace\GoesHere\OtherClass::getData();
        /* Или например - список веб-форм */
        $required_content = \CForm::GetList(
            ($by = "s_sort"),
            ($order = "asc"),
            [],
            $is_filtered
        );

        while ($row = $required_content->Fetch()) {
            /* Из каждого найденного элемента формируем массив */
            $searchData = [
                'ID' => $row['ID'],
                'SITE_ID'=> [$site_id],
                'DATE_CHANGE' => date('d.m.Y H:i:s'),
                'URL' => '/some/url/here',
                'PERMISSIONS'=> [$group_id],
                'TITLE' => $row['DESCRIPTION'],
                'BODY' => $row['DESCRIPTION'],
                'PARAM1' => '',
                'PARAM2' => '',
            ];

            // Передаем массив в функцию индексации
            // это небольшая обертка над CSearch::Index
            $index_res = call_user_func(
                array($oCallback, $callback_method),
                $searchData
            );

            if (!$index_res) {
                return $searchData['ID'];
            }
        }

        return false;
    }
}


Самое ответственное здесь - отследить момент, когда время шага индексирования подходит к концу.
В этом вам помогает значение $index_res. Как только функция индексации $callback_method понимает, что времени на индексацию следующего элемента не хватит, она возвращает false. В этом случае, если у вас остались неиндексированные элементы, наш обработчик возвращает ID последнего проиндексированного значения. И в данных следующей итерации этот ID будет передан в качестве значения в массиве $NS.
То есть вы можете проверить, не пришел ли в $NS какой-либо ID и сузить результат выборки индексируемых элементов.
Естественно, это актуально если вы индексируете over 9000 элементов и за один шаг поиска это сделать не получится.

Кратко о ключах массива, передаваемого в функцию :
ID - некий уникальный ИД индексируемого элемента.
DATE_CHANGE - дата изменения данных элемента, можно ставить текущей датой или какой-то другой важной датой (последнего редактирования и т.п).
TITLE и BODY - основные поставщики данных для поиска. Заголовок и тело записи поискового контента.
SITE_ID - ИД сайтов, на которых доступен данный поисковый контент.
PARAM1 и PARAM2 - дополнительные параметры, по которым можно идентифицировать запись, например для записей инфоблоков это ИД конкретного инфоблока (PARAM2)
PERMISSIONS - ИД групп, которым доступен данный поисковый контент (да-да, можно ограничивать доступ к результатам поиска), обычно достаточно передать ИД группы Все пользователи (2)
URL - URL на который ведет ссылка из результатов поиска
TAGS - возможность добавить теги, мной, к сожалению, не изучена, экспериментируйте самостоятельно.
Также в качестве домашнего задания - зарегистрируйте обработчик переиндексации и создайте его код, используя методы d7.

Напоследок, немного информации о поисковых таблицах. Метод CSearch::Index добавит данные как минимум в три таблицы:
b_search_content - собственно сам поисковый контент,
b_search_content_right - связь поискового контента с группой пользователей, группа записывается в виде G%ИД группы%, например, G2
b_search_content_site - связь поискового контента с конкретным сайтом.

Комментариев нет:

Отправить комментарий