Skip to content
mFilter
mFilter
Фасетная фильтрация для MODX 3 с поддержкой SEO URL
  • MODX 3
  • PHP 8.1
  • Vue 3
  1. Компоненты
  2. mFilter
  3. Рецепты
  4. Синхронизация индекса фасетов

Синхронизация индекса фасетов

Индекс фасетов — копия значений фильтров из таблиц товаров, опций и TV. Если данные изменились, а индекс нет, фильтры покажут устаревшие значения и неверные числа товаров.

Задача

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

Что обновляет индекс само

Что произошлоЧем обновляетсяКогда
Товар сохранён или удалён в админке MODX или MiniShop3Плагин mFilterСразу
Импорт MiniShop3 из CSVПлагин mFilter по событию msOnAfterImportПосле импорта, полной пересборкой
Правка через API MODX — $resource->save(), свой импортёрЗадача Scheduler mfl_sync_facet_indexВ течение 5 минут
Прямой запрос к базе с editedonТа же задачаВ течение 5 минут
Прямой запрос к базе без editedonНичем

Задача сравнивает editedon товаров с временем прошлого запуска. Удалённые товары она находит по deletedon и убирает их из индекса. Поэтому важно не само изменение, а отметка времени: правка, которая её не обновила, для задачи не существует.

Подробности задач — Scheduler-задачи.

Свой импортёр: обновить точечно

Если импортёр знает, какие товары он изменил, пересоберите индекс только для них — это гораздо быстрее полной пересборки:

php
/** @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.

Если у импортёра есть своё событие окончания, тот же вызов можно повесить плагином на него — идентификаторы товаров плагин возьмёт из параметров события.

Когда идентификаторы неизвестны

Тогда остаётся полная пересборка. Три способа:

php
// В фоне, задачей 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. Если импортёр пишет в базу напрямую, есть три пути:

  1. Обновлять editedon в своих запросах — тогда задача подхватит изменения за 5 минут.
  2. Вызывать buildForProducts() или buildAll() в конце своего скрипта.
  3. Поставить mfl_rebuild_facet_index повторяемой задачей — например, раз в неделю ночью, как страховку.

Если индекс отстаёт

Что проверитьГде
Время последней пересборки и число строкВкладка «Обслуживание», блок «Индекс фасетов»
Работает ли задача синхронизацииmfl_cache, ключ facet_index.last_sync_at: время стоит на месте — Scheduler не запускается
Ошибки пересборкиЖурнал ошибок MODX, строки с [mFilter] Facet index

Товары, сохранённые в обход MODX, в списке изменённых не появятся, сколько бы раз задача ни отработала. Для них — полная пересборка.