Налаштування масової зміни властивостей товарів 1С-Бітрікс
У каталозі з 15 000 товарів потрібно проставити нову властивість «Матеріал» у 8 000 позицій певної категорії, виправити помилку в значенні фасетного фільтра у 2 000 товарів, зняти прапорець «Рекомендований» у половини асортименту. Через картку товара це тижні роботи. Завдання вирішується пакетним оновленням через API з контролем цілісності даних.
Де зберігаються властивості
Властивості товарів у Бітрікс зберігаються в кількох місцях залежно від типу:
-
Поля елемента (
NAME,PREVIEW_TEXT,ACTIVEтощо) —b_iblock_element -
Властивості інфоблоку —
b_iblock_element_property, деIBLOCK_PROPERTY_ID— ID властивості,VALUE— значення -
Множинні властивості — кілька рядків у
b_iblock_element_propertyз однимIBLOCK_ELEMENT_IDта однимIBLOCK_PROPERTY_ID -
Властивості типу «Список» —
VALUEмістить текстове значення,VALUE_ENUM_ID— посилання наb_iblock_property_enum
Для торгових пропозицій — аналогічна структура, але IBLOCK_ID вказує на інфоблок пропозицій, а не основний каталог.
Масове оновлення через CIBlockElement::SetPropertyValues
Базовий підхід для невеликих обсягів (до 1 000 елементів):
$iblockId = 10; // ID інфоблоку каталогу
$propertyCode = 'MATERIAL';
$newValue = 'Бавовна 100%';
// Отримуємо список елементів потрібної секції
$res = \CIBlockElement::GetList(
[],
['IBLOCK_ID' => $iblockId, 'SECTION_ID' => 42, 'ACTIVE' => 'Y'],
false,
false,
['ID']
);
while ($row = $res->Fetch()) {
\CIBlockElement::SetPropertyValues(
$row['ID'],
$iblockId,
$newValue,
$propertyCode
);
}
На великих обсягах цей метод повільний — він читає поточні значення, порівнює, оновлює. Кожен виклик — кілька SQL-запитів.
Швидке оновлення через D7 ORM
Для обсягів від 1 000 елементів використовуйте пряме оновлення b_iblock_element_property:
use Bitrix\Iblock\ElementPropertyTable;
// Спочатку отримуємо ID властивості
$propertyId = getPropertyIdByCode($iblockId, 'MATERIAL');
// Отримуємо ID елементів пакетами
$elementIds = getElementIdsBySectionBatch($iblockId, $sectionId, 500);
foreach (array_chunk($elementIds, 500) as $chunk) {
// Перевіряємо, у кого вже є запис
$existing = ElementPropertyTable::getList([
'filter' => [
'IBLOCK_PROPERTY_ID' => $propertyId,
'IBLOCK_ELEMENT_ID' => $chunk,
],
'select' => ['ID', 'IBLOCK_ELEMENT_ID'],
])->fetchAll();
$existingMap = array_column($existing, 'ID', 'IBLOCK_ELEMENT_ID');
foreach ($chunk as $elementId) {
if (isset($existingMap[$elementId])) {
// Оновлюємо наявний запис
ElementPropertyTable::update($existingMap[$elementId], ['VALUE' => 'Бавовна 100%']);
} else {
// Вставляємо новий
ElementPropertyTable::add([
'IBLOCK_ELEMENT_ID' => $elementId,
'IBLOCK_PROPERTY_ID' => $propertyId,
'VALUE' => 'Бавовна 100%',
]);
}
}
}
Після прямої зміни таблиці потрібно скинути кеш інфоблоку:
\Bitrix\Iblock\InformationBlock::cleanTagCache($iblockId);
\Bitrix\Main\Application::getInstance()->getTaggedCache()->clearByTag('iblock_id_' . $iblockId);
Масова зміна значень типу «Список»
Властивості типу «Список» (використовуються у фасетному фільтрі) зберігають у VALUE текстове значення, а у VALUE_ENUM_ID — ID із b_iblock_property_enum. При зміні значення потрібно оновлювати обидва поля.
// Знаходимо ID нового значення в переліку
$enumRes = \CIBlockPropertyEnum::GetList(
[],
['PROPERTY_ID' => $propertyId, 'VALUE' => 'Синій']
);
$enum = $enumRes->Fetch();
$enumId = $enum['ID'];
// Оновлюємо
ElementPropertyTable::update($existingPropId, [
'VALUE' => 'Синій',
'VALUE_ENUM_ID' => $enumId,
]);
Якщо потрібного значення ще немає в переліку — спочатку додайте його через CIBlockProperty::SetEnumValues() або напряму в b_iblock_property_enum.
Оновлення через адміністративний імпорт
Для нетехнічних користувачів або регулярних оновлень краще підходить імпорт CSV через Каталог → Імпорт. Шаблон файлу: перший рядок — заголовки з кодами полів (ID, PROPERTY_MATERIAL, PROPERTY_COLOR). Бітрікс оновлює лише ті властивості, колонки яких присутні у файлі.
Обмеження стандартного імпорту: немає підтримки умов («оновити властивість лише якщо поточне значення порожнє»). Для таких сценаріїв — тільки скрипти.
Інвалідація фасетного індексу
Після масової зміни властивостей, що використовуються у фасетному фільтрі (catalog.smart.filter), необхідно перебудувати індекс:
\Bitrix\Iblock\PropertyIndex\Manager::markIblockToReindex($iblockId);
// або примусово:
$indexer = new \Bitrix\Iblock\PropertyIndex\Indexer($iblockId);
$indexer->startIndex();
$indexer->continueIndex(0);
$indexer->endIndex();
На каталозі 50 000+ товарів переіндексація займає кілька хвилин — запускайте у фоні через агент або cron.
Терміни виконання
| Обсяг | Метод | Час |
|---|---|---|
| До 500 товарів | Admin UI / SetPropertyValues | 1–3 години |
| 500–5 000 товарів | D7 пакетне оновлення | 3–6 годин |
| 5 000–50 000 товарів | D7 + черга + переіндексація | 1–2 дні |







