[FlatFilters] Первые итоги работы.

Приветствую, коллеги! Вам известно, что на данный момент пригодной для коммерческого использования альтернативы mFilter2 нет. Сам mFilter2 прекрасен, но когда на сайте несколько десятков тысяч товаров он начинает жутко тормозить. На данный момент у меня готов рабочий прототип нового компонента, который я назвал FlatFilters. Подробности идеи под катом.

Основная причина медленной работы mFilter2 в том, что он на лету собирает данные для фильтрации из разных таблиц. Поэтому очевидное и самое простое решение: заранее положить все необходимые данные в одну таблицу. Но дьявол как всегда в деталях.

Первый нюанс: какие данные записывать? В прототипе используется файл конфигурации, где указывается какие поля брать, как хранить и как фильтровать. По умолчанию собираются данные из таблиц ресурсов, товаров, переменных шаблонов, опций товара. К релизу добавлю возможность через плагин добавлять любые кастомные таблицы для поиска полей и их значений.

Второй нюанс: куда записывать данные? Кто писал компоненты для Modx, тот знает, что есть встроенные методы для создания моделей по XML схеме. Собственно их и было решено использовать для создания моделей по конфигурации и таблиц в БД. Это означает, что можно создавать конфигурации для каждой категории, таким образом можно регулировать размер таблиц с индексами и как следствие управлять скоростью фильтрации.

Следующая проблема: как поддерживать актуальность данных? Плагин на сохранение ресурса, который обновить индекс. Пока для его работы необходимо, чтобы ключ конфигурации в файле совпадал с id какой-либо категории.

Тут стоит упомянуть об улучшениях в сравнении с mFilter2. Благодаря измененной структуре хранения данных появилась возможность фильтрации по множественным значения. Однако в этом есть и минусы. Например, если у вас есть 5 опций товара, каждая из которых может иметь по 5 значений (ситуация чисто умозрительная на практике такого не встречал), то на один товар будет создано 5 в пятой степени индексов или 3125 записей в БД на один товар. Следовательно следует избегать большого количества опций со множественным выбором.
Также есть возможность фильтрации по полям типа migx, причем можно указать несколько полей, которые составят своего рода модификацию.
Для диапазонов и простых фильтров работает приведение типов через CAST, т.е. числа фильтруются как числа, даты как даты, строки как строки и не важно какой тип данных имеет исходное поле. Множественные значения фильтруются через IN и не приводятся к конкретному типу.

Далее хочу сказать о минусах: не удалось интегрировать pdoPage, пришлось писать свою пагинацию. На этом о минусах всё)))

В целом, возможностей у компонента будет масса. Можно будет указать свой сниппет для рендера, свой сниппет для обработки запросов с фронта, подключить свой слайдер для выбора диапазона чисел, свой пикер для выбора диапазона дат и множество событий для внедрения вашей логики. Подробная инструкция появится вместе с релизом компонента.

Посмотреть как работает компонент сейчас можно тут Для понимания: на сайте 104014 товаров, в таблице индексов примерно 170000 записей. Скорость обработки запроса выводится на экран.

Единственная проблема, которую не удалось решить на данный момент это блокирование недоступных значений. При включении этой опции время работы скрипта возрастает до 2 секунд. Если есть идеи как решить эту проблему пишите в комментариях.
Артур Шевченко
12 ноября 2023, 21:06
modx.pro
2
969
+17
Поблагодарить автора Отправить деньги

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

Александр Туниеков
12 ноября 2023, 21:15
0
Привет. Тут немного не понятно. А сами фильтры как формируются? В mfilter2 назначаешь поле и тебе в фильтер вываливаются доступные параметры. А у тебя как? Параметры вручную прописываешь?
В mfilter2 как раз подбор доступных параметров и занимает основное время. Сама фильтрация поиск по запрошенным параметрам это не долго.
    Артур Шевченко
    12 ноября 2023, 23:21
    0
    В первой версии скорее всего будет только конфиг примерно такой
    return [
        12 => [
            'filters' => [
                'width' => [
                    'filter_type' => 'numrange',
                    'field_type' => 'number'
                ]
            ]
        ]
    ]
    12 — id категории, width — опция. По этой конфигурации будет создана таблица в БД с полями id, rid, width в которую будут записаны значения опции width для каждого товара. В шаблоне ты будешь вызывать сниппет и указывать ему параметр configName = 12 и шаблоны для каждого поля, по аналогии c mFilter2, а он тебе отрисует фильтры.
      Александр Туниеков
      13 ноября 2023, 00:23
      0
      Интересно. Обычно вроде в mfilter2 у каждой категории товаров делают свои фильтры. Или если магазин простой, то для всех категорий один фильтр. Автоматическая сборка значений опций поможет сделать таблицу значений опций, но если таблица будет одна для опции и всех категорий, то в фильтр будут попадать значения опций из других категорий. А если для каждой категории и опции своя таблица, то это дофига раздует базу :-).
      В фасетном поиске (фильтрации) самая проблема получить список значений опций. Чтоб не было не нужных значений и делалась агрегация(предварительный подсчет кол-ва товаров для значения опции). А сам то поиск штука не хитрая select join where значение опции = 'шина' например и это делается быстро и базу не особо грузит. Насколько я разбирался то, как сделано в мфильтер решение по моему оптимальное (за исключением кеширования) на php. Лучше только будут специализированные сервера Elasticsearch, Sphinx и т.д.
      Ну у тебя может получиться что-то интересное, но мне вот сомнительно :-(. Я к тому что ты зря работу не делал. Но если и не получиться то будет опыт :-). Ну посмотрим. Вдруг ты придумаешь что-то сверхестественное ;-)
        Артур Шевченко
        13 ноября 2023, 07:03
        0
        Начнем с того, что mfilter хоть и оптимальное решение, но сама схема таблиц такова, что при большом количестве товаров, даже с отключённой агрегацией, фильтры работают медленно. Кстати в моем компоненте агрегации нет, я ей никогда не пользовался и практический смысл её весьма сомнительный, но не суть. Ничего гениального я не придумал, принцип работы остался тем же: выбираем по каким полям фильтровать, выводим эти поля на фронт фильтруем. Разница только в том, что значения для фильтрации заранее собираются в отдельную таблицу(для маленьких сайтов) или в несколько таблиц(для больших). Что касается раздувания БД, то в текущей реализации у меня к 100К товаров 170К индексов(так я называю собранные для фильтрации данные). Если злоупотреблять опциями с множественным выбором, то можно конечно таблицу раздуть знатно. Опять же, это уже вторая версия, в первой индекс строился иначе, и там в БД было больше миллиона записей, однако запросы отрабатывали менее чем за 1сек, и если бы не проблема с невозможностью фильтрациии по множественным знаниям, я бы схему индексации менять не стал.
      Wassi Wassinen
      14 ноября 2023, 23:09
      +1
      Артур, вы молодец. Я НЕ знаю — вы хотите платное распространение или свободное. Если платное — нужен интерфейс для формирования (подбора) фильтров в админке MODx.
      Ваш компонент SendIt хорош. Но он хорош для программистов. А это 5% пользователей MODx.

      Вне зависимости от сценария распространения вашего компонента (платный или бесплатный) — если хотите массового принятия и внедрения для своего продукта, то нужен понятный и доступный простому пользователю графический интерфейс.

      ИМХО. На истинность не претендую.
        Артур Шевченко
        14 ноября 2023, 23:39
        +2
        В первой версии интерфейса не будет и он будет бесплатным. Как только появится интерфейс — станет платным.
        А в целом, я делаю компоненты для разработчиков, потому как считаю, что каждый должен заниматься своим делом: разработчик — разрабатывать, заказчик — заказывать:-) К тому же SendIt можно прикрутить интерфейс на Migx, пример есть в доке, но мне как разработчику удобнее с файлами работать, а заказчику зачастую надо всё на одну почту слать. Вот и зачем ему интерфейс? С фильтрами, конечно, другая история, тут админка нужна и она будет, но сначала надо обкатать компонент. Учитывая активность сообщества, чем раньше я выпущу компонент, тем быстрее его обкатают. А разработка админки займёт много времени, так как я хочу её на Vue сделать, с ним я знаком мало.
          Wassi Wassinen
          15 ноября 2023, 09:22
          +1
          Стараюсь рассуждать не в категориях «для разработчиков или не для разработчиков». Скорее, про такие категории как востребованность, популярность и т.д. Создателю чего бы то ни было (курсы, книги, программные продукты) хочется востребованности. Это один из видов мотивации создавать что-то новое и совершенствовать свои творения. :)

          Вы делаете классное дополнение. Хочется, чтобы оно получило признание и популярность в сообществе. А для этого нужен интерфейс. Потому что большинство в сообществе MODx не умеют в конфиги, код и т.д. И это не плохо. MODx поэтому обрел популярность. Сейчас наблюдаю тенденцию к уходу от этой концепции. И это не способствует популяризации MODx.
            Wassi Wassinen
            15 ноября 2023, 09:25
            +1
            Если говорить про функциональность — на демке не увидел кнопки «Показать ещё». Для подгрузки страниц не пагинацией, а кнопкой, которая выводит N товаров на той же странице. Часто востребованная опция.
              Артур Шевченко
              15 ноября 2023, 10:28
              0
              Да об этом я думал и скорее всего добавлю её в коробку, но уже на релизе.
                Wassi Wassinen
                15 ноября 2023, 11:40
                0
                Супер. И ещё раз — вы молодец!
                  Wassi Wassinen
                  18 ноября 2023, 16:28
                  0
                  Артур, ещё один важный вопрос — вы будете выпускать FlatFilters только для второй версии MODx или сразу для второй и третьей?
                    Артур Шевченко
                    18 ноября 2023, 21:37
                    0
                    Сначала только для второй, в следующем году для третьей.
        Александр
        12 ноября 2023, 21:57
        0
        Ждем бету, хотелось бы протестировать его на каком-нибудь боевом проекте)
        И ещё вопрос, будет только фильтрация или как в mSearch2 так же поиск будет?
        Arahort
        12 ноября 2023, 23:00
        0
        У демо страницы беда печаль с мобильной версией
          Miša Bulic
          12 ноября 2023, 23:08
          +1
          на то она и демо =)
          Константин Ильин
          14 ноября 2023, 10:11
          0
          Очень жду! на сайте 70к товаров — тормозит… еще и jquery тянет msearch2

          тут выше говорится о вызове компонента, надеюсь будет все просто понятно и главное привычно(как все сниппеты модх) :)

          наконец нашелся смельчак!)
            Николай Савин
            14 ноября 2023, 10:29
            0
            Просто и понятно — это обычно не об Артуре ))
              Константин Ильин
              14 ноября 2023, 11:05
              0
              я как раз с намеком на SendIt))) для меня темный лес) ну и не желание вникать кончено же в непонятное)
                Артур Шевченко
                14 ноября 2023, 11:22
                1
                +2
                Ничто там непонятного? Вот был у тебя вызов
                {'!AjaxForm' | snippet: [
                'validate' => 'name:required,phone:required',
                'successMessage' => 'Форма отправлена!',
                'hooks' => 'email',
                'emailTo' => 'some@email.ru',
                'emailTpl' => 'defaultEmail',
                'form' => 'defaultForm'
                ]}
                Ты копируешь в файл core/components/sendit/presets/sendit.inc.php
                return [
                    'default' => [
                        'validate' => 'name:required,phone:required',
                        'successMessage' => 'Форма отправлена!',
                        'hooks' => 'email',
                        'emailTo' => 'some@email.ru',
                        'emailTpl' => 'defaultEmail',
                        ]
                ]
                А вместо вызова сниппета вставляешь саму форму, которой добавляешь два атрибута data-si-form=«defaultForm», data-si-preset=«default». Всё форма работает. Согласен непривычно, но ничего сложного. Возможно стоит в доку добавить раздел Миграция с AjaxForm.

                А по фильтрам, там SendIt идёт как зависимость, но сниппеты будут вызываться классическим способом)))
                  Ivan
                  14 ноября 2023, 16:45
                  0
                  Сейчас есть такая проблемка. Когда выбираешь производителя, а затем нажимаешь ВСЕ (точнее Производитель), то после фильтрации если первый раз открыть селект в доступных будет только выбранный.
                    Артур Шевченко
                    14 ноября 2023, 19:35
                    0
                    Думаю это связано с тем, что фильтры работают в два этапа. На первом происходит фильтрация и возврат результатов. На втором — поиск недоступных для выбора значений. Изначально всё делалось за один запрос, но тогда ответ приходил через 1.5-2 секунды.
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            23