mSearch: поиск + фильтр для MODX Revolution



    Что-то блог MODX на Хабре совсем зачах, нужно его немного оживить. Хочу представить вам свой компонент, который недавно был практически полностью переписан и расширен.

    Он называется mSearch и сначала задумывался как простейший поиск по сайту, с учетом морфологии русского языка. То есть, нужно было простое и легкое решение для любого сайта, без установки Sphinx и других серьезных систем.

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


    mSearch


    Это сниппет и плагин. Сниппет ищет, плагин индексирует документы при сохранении.

    Установка, как обычно, из репозитория, в 4 клика. При этом, вам будет предложено скачать и установить словари phpMorphy для русского языка — не отказывайтесь.

    Если вы устанавливаете расширение на рабочий сайт, нужно будет проиндексировать имеющиеся документы. Делается это просто:
    [[!mSearch?
    &indexer=`1`
    &offset=`0`
    &limit=`200`
    ]]

    Первый параметр показывает, что мы не ищем, а индексируем, а второй и третий — ограничение выборки, для больших сайтов. Если документов много, а сервер дохлый — придется работать в несколько запусков, меняя значение offset, в данном примере сначала 0, потом 200, потом 400 и т.д.

    Индексация нужна только один раз, после установки на сайт, если там есть документы. Потом индексировать будет плагин mSearchIndexer при сохранении документов.

    Все параметры mSearch вы можете увидеть в свойствах сниппета, а сюда я напишу только основные:
    • &indexer — включение индексации. Нужно только один раз, после установки.
    • &indexFields — какие поля ресурса индексировать?
    • &disablePhpMorphy — отключение phpMorphy. Поиск становится гораздо менее точным.
    • &includeMS — при выводе результатов включать свойста товаров из miniShop.
    • &includeTVs — при выводе товаров включать ТВ параметры.
    • &includeTVList — список имен ТВ параметров, через запятую, для вывода.
    • &parents — список родителей, в которых будет производиться поиск на глубину 10 вложений, через запятую.
    • &returnIds — вместо оформленных результатов возвращать id найденных страниц, через запятую.
    • &resources — список обязательных ресурсов, через запятую, в которых будет произведен поиск.
    • &templates — искать только среди ресурсов с этими номерами шаблонов, через запятую.
    • &tpl — шаблон оформления вывода.
    • &where — JSON выражения для тонкой настройки вывода найденных ресурсов.

    Параметры indexFields, includeTVs, includeTVList, disablePhpMorphy есть и у плагина. Они отвечают за индексацию ресурса при обновлении.
    Также эти параметры влияют и на первичную индексацию (&indexer=`1`).

    Обращая ваше внимание, что множество параметров не случайно называются как у getResources. Это означает, что и работают они так же. Сниппет прекрасно поддерживает вывод с пагинацией через getPage и может, в некоторых случая, спокойно заменять getResources.

    Поиск идет по таблице индекса, что дает неплохую скорость, даже при большом количестве документов, проверял на ~6000 шт.

    Конечно, этот метод не идеален, с релевантностью не все гладко, но лучше решения для русского языка и MODX в любом случае нет. Главное, на мой взгляд то, что можно довольно хорошо уточнить где искать, с каким шаблоном, среди каких родителей и т.д. Ну а параметр &where позволяет и вовсе, как угодно настроить поиск.

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

    Логичным применением mSearch стал поиск по товарам магазина, и вывод найденных результатов, вместо getResources. А это в свою очередь развилось в написание сниппета mFilter, для гибкой фильтрации найденных товаров.

    mFilter


    Это второй сниппет в mSearch. Он самостоятельно генерирует фильтры для найденных (или заранее указанных) ресурсов, используя чанки для оформления. Цифровые значения по умолчанию выводятся как слайдер, текстовые — как чекбоксы.

    Фильтры строятся по ТВ параметрам ресурсов, и\или свойств товаров miniShop.

    Выглядит это вот так.

    Вы видите слева параметры, справа результаты поиска на моем демо-сайте по фразе «Sony». Возле каждого параметра есть циферки — это количество результатов, которое вы получите при выборе это параметра. То есть, все варианты фильтра просчитываются на лету, и невозможные комбинации отключаются.

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

    Работает довольно шустро, но на действительно больших объемах пока не проверял.

    Основные параметры mFilter:
    • &resources — список ресурсов для работы, через запятую. Если не указать, попытается поискать результаты через mFilter.
    • &includeTVs — включить ТВ для генерации фильтров
    • &includeTVList — использовать эти ТВ, через запятую
    • &excludeTVList — не использовать эти ТВ, через запятую
    • &includeMS — брать параметры miniShop для построения фильтра
    • &includeMSList — какие именно поля товаров miniShop использовать для фильтра
    • &sortFilters — порядок вывода фильтров, с префиксами, например: `tv_category,tv_subcategory,ms_add2,tv_color,tv_size,tv_action,ms_price`
    • + если будете искать ресурсы, то любые параметры mSearch
    • + любые параметры getPage и\или getResources\msGetResources

    Для вывода результатов фильтра необходимы сниппеты getPage, getResources (если используете miniShop — msGetResources).

    Также требуются jquery плагины:
    jQuery 1.7+ — основной помошник
    jQueryUI 1.8+ — нужен только виджет slider для цен и других числовых значений
    jQuery Form 2.7+ — отправка формы и прием ответа

    Для вывода товаров из определенной категории магазина miniShop можно использовать такой сниппет getCatIds:
    if (!empty($_REQUEST['query'])) {return;}
    $parent = $modx->resource->id;
    
    $tmp = $modx->getChildIds($parent);
    if (empty($tmp)) {return 0;}
    $tpls = explode(',', $modx->getOption('minishop.goods_tpl'));
    $q = $modx->newQuery('modResource', array('id:IN' => $tmp, 'template:IN' => $tpls, 'deleted:!=' => 1, 'published' => 1));
    $q->select('id');
    if ($q->prepare() && $q->stmt->execute()) {
        $ids = $q->stmt->fetchAll(PDO::FETCH_COLUMN, 0);
        return implode(',', $ids);
    }
    

    Пример вызова:
    [[!mFilter?
    &resources=`[[!getCatIds]]`
    &includeTVs=`1`
    &includeTVList=`category,color,size,action`
    &includeMS=`1`
    &includeMSList=`add2,price`
    &tpl=`tpl.msGoods.row`
    &templates=`5`
    &sortFilters=`tv_category,tv_subcategory,ms_add2,tv_color,tv_size,tv_action,ms_price`
    ]]


    Заключение


    Все чанки оформления и js скрипт для работы идут в комплекте. Конечно, не факт, что у вас все получится настроить как надо с первого раза, для этого нужны кое-какие знания MODX, jQuery и понимание работы Ajax. При всех «не работает!» первым делом смотрите в консоль своего браузера на предмет ошибок javascript.

    Но я, как смог, постарался упростить задачу построения фильтра. И теперь, при определенном желании, вы сможете сделать это у себя на сайте\магазине.

    Вы можете посмотреть в админке моего демо-сайта, как включены фильтр и поиск. Логин и пароль: test.

    Кстати
    Вся работа над mFilter была заказа и оплачена веб-студией Simple Dream.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 5

      +2
      Когда-то нужно было сделать подобие mFilter, заказал, мне его сделали, но к сожалению, он работал напрямую с базой, поэтому адаптировать его под другие сайты было проблематично. Ваш вариант более прост и универсален. Спасибо! Я смотрю, Василий, вы большой вклад вносите в русскоязычную среду пользователей MODx Revo. И за это Вам отдельное спасибо :)
        +1
        На здоровье!
          +2
          Большую работу проделали, а самое главное очень и очень полезную.
          Присоединяюсь к благодарящим. :)
        +1
        Отлично, спасибо!.. Тоже использовал phpmorphy на своих проектах, а теперь пригодится и для MODx.
        Жаль, что словари у phpmorphy давно не обновлялись.
          +1
          mFilter — просто красота, как раз начал проектировать что-то подобное, но писать начать пока не успел

          Only users with full accounts can post comments. Log in, please.