В каждом интернет магазине на платформе Bitrix в каталоге есть и используется компонент “Умный фильтр” (bitrix:catalog.smart.filter), этот компонент входит в стандартный пакет поставки CMS Bitrix и позволяет организовать фильтрацию по свойствам товара в каталоге, что существенно для покупателя упрощает поиск нужного товара. Что бы фильтрация товаров по свойствам работала приемлемо быстро разработчики Bitrix придумали делать подборки результатов фильтра не из таблиц инфоблока, а при помощи специального “фасета”.
С сайта Битрикс:
В функционал «Умного фильтра» встроен фасетный индекс. Использование «фасеты» на порядок ускоряет поиск внутри магазина. Фасетный поиск работает практически мгновенно, выполняет запросы по многим параметрам и не нагружает при этом систему.
Ваши клиенты не будут нервничать в ожидании результатов поиска. Встроенный фасетный поиск позволяет последовательно выбрать товары с нужными свойствами, отсеяв все лишнее. Система моментально выдает по любому запросу заранее подготовленные списки товаров. С фасетной навигацией покупателям легче и проще выбрать товар даже в огромном каталоге.
При добавлении новых свойств товаров, Битрикс будет просить перестроить фасетный индекс и это сделать достаточно просто, через административную панель сайта:

Если состояние фасета отмечено красным, значит нужно нажать кнопку создать и дождаться пересоздания индекса, после этого фильтрация в умном фильтре снова будет работать корректно и охватывать всей свойства товаров вашего каталога.
Если речь идёт о регулярной загрузке товаров из учётной программе или при обмене товарами при помощи json, csv, xml и при автоматическом заведении свойств товара в информационном блоке встаёт вопрос о том как же программно пересоздать фасетный индекс, а так же как проверить нуждается ли информационный блок в пересоздании фасетного индекса.
Для того что бы проверить нуждается ли инфоблок в создании нового индекса достаточно функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * Проверяет нужна ли индексация информационному блоку * @return boolean true - требуется индексация */ function check_iblock_index($iblock_id) { $iblockInfo = \Bitrix\Iblock\IblockTable::getList(array( 'select' => array('ID', 'PROPERTY_INDEX'), 'filter' => array('=ID' => $iblock_id) ))->fetch(); return ($iblockInfo['PROPERTY_INDEX'] == 'I'); } |
В качестве параметра функция принимает ИД инфоблока и возвращает true – если требуется создание фасета.
И так, если мы знаем, что нужно создать фасет и хотим это сделать программно из кода, тогда воспользуемся следующей функцией:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/** * Создание фасетного индекса * @param array $params Параметры запуска согласно ключам в функции */ function reindex_iblock($params) { /** * Параметры по умолчанию */ $default_params = [ 'cnt' => 0, //Всего элементов проиндексированно 'last_id' => 0, //Последний элемент 'total' => 0, //Всего элементов 'iblock_id' => 4, //ИД инфоблока 'max_execution_time' => 60, //время исполнения 'first_start' => false, //Первый запуск ]; $params = array_merge($default_params, $params); $index = \Bitrix\Iblock\PropertyIndex\Manager::createIndexer($params['iblock_id']); if ($params['first_start']) { $params['cnt'] = 0; $params['last_id'] = 0; $index->startIndex(); $params['total'] = $index->estimateElementCount(); $params['first_start'] = false; } $index->setLastElementId($params['last_id']); $res = $index->continueIndex($params['max_execution_time']); if ($res > 0) { $params['cnt'] += $res; $params['last_id'] = $index->getLastElementId(); } else { $index->endIndex(); \CBitrixComponent::clearComponentCache("bitrix:catalog.smart.filter"); \CIBlock::clearIblockTagCache($params['iblock_id']); } return $params; } |
При передаче функции стартовых параметров, начнётся процесс создания фасета. Если товаров много, то этот процесс лучше разбить на шаги. Что бы ограничить время на 1-н шаг, достаточно в массив параметров функции передавать ключ “max_execution_time” с нужным временем в секундах. При создании индекса, функция будет возвращать массив:
1 2 3 4 5 6 7 8 9 10 |
[ 'cnt' => 0, //Всего элементов проиндексированно 'last_id' => 0, //Последний элемент 'total' => 0, //Всего элементов 'iblock_id' => 4, //ИД инфоблока 'max_execution_time' => 60, //время исполнения ]; |
когда cnt станет равно total – значит можно прекратить процесс пересоздания индекса.
Ниже пример реализации пересоздания индекса на обычной странице сайта с передачей параметров между запросами через GET. Обработка каталога товаров с количеством более 100К позиций.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php"); $default_params = [ 'cnt' => 0, //Всего элементов проиндексированно 'last_id' => 0, //Последний элемент 'total' => 0, //Всего элементов 'iblock_id' => 4, //ИД инфоблока 'max_execution_time' => 30, //время исполнения 'first_start' => true, //Первый запуск ]; $url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[SCRIPT_NAME]"; if (empty($_GET['reindex'])) { $load = propertyUploadJson::getInstance()->reindex_iblock($default_params); $load['reindex'] = 'y'; $load['step'] = 1; header("Refresh: 2;" . $url . '?' . http_build_query($load)); exit(); } elseif ($_GET['cnt'] == $_GET['total']) { die('Reindex finish!'); } else { $load = propertyUploadJson::getInstance()->reindex_iblock( [ 'cnt' => $_GET['cnt'] ?? 0, 'last_id' => $_GET['last_id'] ?? 0, 'total' => $_GET['total'] ?? 0, 'iblock_id' => 4, 'max_execution_time' => 20, 'first_start' => false, ] ); $load['reindex'] = 'y'; $load['step'] += $_GET['step']; header("Refresh: 2;" . $url . '?' . http_build_query($load)); exit(); } |
Этот скрипт требует доработки. Вот что у меня получилось в итоге
(не забудьте сменить iblock_id на свой)
require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
use \Bitrix\Main\Loader;
Loader::includeModule('iblock');
/**
* Создание фасетного индекса
* @param array $params Параметры запуска согласно ключам в функции
*/
function reindex_iblock($params) {
/**
* Параметры по умолчанию
*/
$default_params = [
'cnt' => 0, //Всего элементов проиндексированно
'last_id' => 0, //Последний элемент
'total' => 0, //Всего элементов
'iblock_id' => 12, //ИД инфоблока
'max_execution_time' => 30, //время исполнения
'first_start' => false, //Первый запуск
];
$params = array_merge($default_params, $params);
$index = \Bitrix\Iblock\PropertyIndex\Manager::createIndexer($params['iblock_id']);
if ($params['first_start']) {
$params['cnt'] = 0;
$params['last_id'] = 0;
$index->startIndex();
$params['total'] = $index->estimateElementCount();
$params['first_start'] = false;
}
$index->setLastElementId($params['last_id']);
$res = $index->continueIndex($params['max_execution_time']);
if ($res > 0) {
$params['cnt'] += $res;
$params['last_id'] = $index->getLastElementId();
} else {
$index->endIndex();
\CBitrixComponent::clearComponentCache("bitrix:catalog.smart.filter");
\CIBlock::clearIblockTagCache($params['iblock_id']);
}
return $params;
}
$default_params = [
'cnt' => 0, //Всего элементов проиндексированно
'last_id' => 0, //Последний элемент
'total' => 0, //Всего элементов
'iblock_id' => 12, //ИД инфоблока
'max_execution_time' => 30, //время исполнения
'first_start' => true, //Первый запуск
];
$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[SCRIPT_NAME]";
if (empty($_GET['reindex'])) {
$load = reindex_iblock($default_params);
$load['reindex'] = 'y';
$load['step'] = 1;
header("Refresh: 2;" . $url . '?' . http_build_query($load));
exit();
} elseif ($_GET['cnt'] == $_GET['total']) {
die('Reindex finish!');
} else {
$load = reindex_iblock(
[
'cnt' => $_GET['cnt'] ? $_GET['cnt'] : 0,
'last_id' => $_GET['last_id'] ? $_GET['last_id'] : 0,
'total' => $_GET['total'] ? $_GET['total'] : 0,
'iblock_id' => 12,
'max_execution_time' => 20,
'first_start' => false,
]
);
$load['reindex'] = 'y';
$load['step'] += $_GET['step'];
header("Refresh: 2;" . $url . '?' . http_build_query($load));
exit();
}
Дурацкий парсер заменил кавычки.
Елочки заменить на двойные кавычки.
А апострофы на одинарные
Замените кавычки на правильные. Дурацкий парсер этого сайта все переиначил