
Синхронизация индекса фасетов
Индекс фасетов — копия значений фильтров из таблиц товаров, опций и TV. Если данные изменились, а индекс нет, фильтры покажут устаревшие значения и неверные числа товаров.
Задача
Понять, когда индекс обновляется сам, и обновить его вручную там, где автоматики не хватает: свой импортёр, прямые запросы к базе.
Что обновляет индекс само
| Что произошло | Чем обновляется | Когда |
|---|---|---|
| Товар сохранён или удалён в админке MODX или MiniShop3 | Плагин mFilter | Сразу |
| Импорт MiniShop3 из CSV | Плагин mFilter по событию msOnAfterImport | После импорта, полной пересборкой |
Правка через API MODX — $resource->save(), свой импортёр | Задача Scheduler mfl_sync_facet_index | В течение 5 минут |
Прямой запрос к базе с editedon | Та же задача | В течение 5 минут |
Прямой запрос к базе без editedon | Ничем | — |
Задача сравнивает editedon товаров с временем прошлого запуска. Удалённые товары она находит по deletedon и убирает их из индекса. Поэтому важно не само изменение, а отметка времени: правка, которая её не обновила, для задачи не существует.
Подробности задач — Scheduler-задачи.
Свой импортёр: обновить точечно
Если импортёр знает, какие товары он изменил, пересоберите индекс только для них — это гораздо быстрее полной пересборки:
/** @var \MFilter\MFilter $mfilter */
$mfilter = $modx->services->get('mfilter');
$builder = $mfilter->getFacetIndexBuilder();
$updatedIds = [];
foreach ($rows as $row) {
$resource = $modx->getObject(\MODX\Revolution\modResource::class, $row['id']);
if (!$resource) {
continue;
}
$resource->set('pagetitle', $row['name']);
$resource->save();
$updatedIds[] = $resource->get('id');
}
// Один вызов после всего импорта
if ($updatedIds) {
$stats = $builder->buildForProducts($updatedIds);
$modx->log(modX::LOG_LEVEL_ERROR, "[Импорт] Индекс фасетов: {$stats['products']} товаров за {$stats['duration_ms']} мс");
}buildForProducts() возвращает products, text_rows, num_rows и duration_ms.
Если у импортёра есть своё событие окончания, тот же вызов можно повесить плагином на него — идентификаторы товаров плагин возьмёт из параметров события.
Когда идентификаторы неизвестны
Тогда остаётся полная пересборка. Три способа:
// В фоне, задачей Scheduler
$scheduler = $modx->services->get('scheduler');
$task = $scheduler->getTask('mfilter', 'mfl_rebuild_facet_index');
if ($task) {
$task->schedule('+0 seconds');
}
// Сразу, в своём CLI-скрипте
$mfilter->getFacetIndexBuilder()->buildAll();Третий способ — кнопки «Пересобрать сейчас» и «Через Scheduler» на вкладке Обслуживание. Полная пересборка тяжелее точечной, поэтому на больших каталогах запускайте её в фоне.
Прямые запросы к базе
Задача синхронизации видит только изменения с новым editedon. Если импортёр пишет в базу напрямую, есть три пути:
- Обновлять
editedonв своих запросах — тогда задача подхватит изменения за 5 минут. - Вызывать
buildForProducts()илиbuildAll()в конце своего скрипта. - Поставить
mfl_rebuild_facet_indexповторяемой задачей — например, раз в неделю ночью, как страховку.
Если индекс отстаёт
| Что проверить | Где |
|---|---|
| Время последней пересборки и число строк | Вкладка «Обслуживание», блок «Индекс фасетов» |
| Работает ли задача синхронизации | mfl_cache, ключ facet_index.last_sync_at: время стоит на месте — Scheduler не запускается |
| Ошибки пересборки | Журнал ошибок MODX, строки с [mFilter] Facet index |
Товары, сохранённые в обход MODX, в списке изменённых не появятся, сколько бы раз задача ни отработала. Для них — полная пересборка.
