Фасетный поиск в Drupal: часть третья

03 May, 2014

Часть первая / Часть вторая / Часть третья

Множественный выбор (чекбоксы в фильтре)

Мне также хотелось, чтобы можно было выбрать одновременно несколько брендов или категорий в нашем фильтре. Нужный функционал обнаружился в dev-версии модуля search api db. Поэтому скачиваем dev-версию, после чего в настройках виджета меняем 'ссылки' на 'ссылки с чекбоксами', а оператор ставим 'OR' вместо 'AND'.
Checkboxes Widget

OR operator

Теперь в фильтре можно выбирать несколько позиций сразу:
Checkboxes example

Патчим Jquery UI Slider: исправляем выбор значений

Search API range example
Для выбора диапазона значений есть отличный модуль Search Api ranges, который легко интегрирует jQuery UI min/max slider в наш фильтр. Обычно подобные виджеты применяют для выбора диапазона цен, но можно придумать и другие ситуации, где он будет полезен.
По дефолту модуль имеет странное поведение - диапазон можно только уменьшить, но не увеличить, что несколько нелогично. К счастью, я нашел патч, который исправляет данный косяк. Я применял патч для версии 7x-1.5.
Страница обсуждения проблемы: https://drupal.org/node/1989776
Сам патч: http://drupalcode.org/project/search_api_ranges.git/commitdiff/433bbcd?h...

--- a/search_api_ranges.module
+++ b/search_api_ranges.module
@@ -144,11 +144,8 @@ function search_api_ranges_minmax($variables, $order = 'ASC') {
   // otherwise our min/max would always equal user input.
   $filters = &$query->getFilter()->getFilters();
   foreach ($filters as $key => $filter) {
-
-    // Check for array: old style filters are objects which we can skip.
-    if (is_array($filter)) {
-      if ($filter[0] == $variables['range_field'] || ($filter[0] != $variables['range_field'] && $filter[2] == '<>')) {
-        $current_filter = $filters[$key];
+    if( isset($filter->tags) && is_array($filter->tags) ){
+      if( in_array('facet:'.$variables['range_field'], $filter->tags) ){
         unset($filters[$key]);
     }
}

Патчим JQuery UI Slider: настраиваем редирект

В версии модуля 7х-1.5 я столкнулся с тем, что если виджет слайдера расположен на странице, отличной от страницы поиска (а в моем случае блоки с фильтром были почти на всех страницах), то после изменения диапазона (цены) шло перенаправление на текущую страницу, а не на страницу поиска.
Глянув на код, я понял, что косяк скрыт в функии search_api_ranges_block_slider_view_form_submit() (файл search_api_ranges.module, строка 364).
Я не стал особо разбираться, что там и зачем, просто немного изменил код в строке 427:

-     drupal_goto($path, array('query' => array($params), 'language' => $language));
+    drupal_goto($values['path'], array('query' => array($params), 'language' => $language));

после чего проблема решилась.

Часть первая / Часть вторая / Часть третья

17 комментариев

by Альберт on пн, 07/07/2014 - 11:45

Статья класс!

А как убрать автосабмит но оставить ajax обновление значений?

by DreamR1der on пн, 08/09/2014 - 22:29

Посмотрите этот модуль: https://www.drupal.org/project/ajax_facets, судя по видео, как раз оно, правда, сам не использовал.
В описании к модулю говорится, что ему нужен для работы Search api solr, но ветка 7.х-3.х должна работать и с Search api db.

by Dex on вс, 07/09/2014 - 17:34

Спасибо за труды! туториал просто супер!

by Dex on чт, 11/09/2014 - 13:38

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

by Dex on чт, 11/09/2014 - 13:39

аааа, или это и есть речь про патч?

by DreamR1der on чт, 11/09/2014 - 22:59

Верно, патч про это :)

by Dex on пн, 15/09/2014 - 20:26

А вы случайно не знаете, как можно организовать следующее? а то голова уже едет. Нужно сделать фасетный поиск, например по запчастям, у этого материала есть поле референс, к авто которому эта запчасть подходит, и как настроить фасет чтобы поля из материала референса были доступны в фасетах запчастей? Может натолкнете на мысль? Иными словами, запчасть принадлежит к материалу авто, у этого материала есть год, марка, модель, итд, и вот эти поля должны быть при поиске запчасти. м? С меня пивас за идею)

by DreamR1der on пн, 15/09/2014 - 23:51

Гляньте, как сделан drupal commerce kickstart 2. Там тоже reference используется и фасетный поиск - Product Display имеет reference-ссылку на товары, которые в него входят. При этом в фасетном поиске доступен, к примеру, фильтр по цвету и цене (эти поля относятся к товару, а не к Product Display). Как раз то, что вам надо, если я все верно понял.

Вкратце, то во вьюхе надо добавить "Связь -> твое reference поле", тогда поля материала, на который ссылаются в этом поле, будут доступны в этой вьюхе, и можно будет фасетный фильтр сделать по ним. Также надо включить агрегацию, чтобы авто не дублировались.
Можете глянуть пример здесь: http://dreamr1der.ru/drupal_commerce_2#5, там без фасетного поиска, но по связям и агрегации должно быть понятно. Также советую книгу "Byron A. - Using Drupal 2nd Edition - 2012", раздел по созданию инет-магазина. А дальше смотрите commerce kickstart 2.

Больше пока ничем помочь не могу, ушел в отпуск до конца месяца.

by Dex on вт, 16/09/2014 - 09:12

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

by Антон on вс, 05/10/2014 - 22:44

Спасибо автору за труд! Отлично и помогло. Очень приятно что рассмотрены такие ньюансы, как dev - весрии модулей

by DreamR1der on вс, 05/10/2014 - 23:49

Вай, пасиб!

by SoTKoM on вт, 11/11/2014 - 10:23

Спасибо за статьи! помогли... А не подскажите, как вывести в блок текстовый инпут для поиска по заголовкам? Может конечно и тривиальная задача (не попадалась ни в одном описании search api), но все же никак не могу сообразить.

by DreamR1der on вт, 11/11/2014 - 17:55

Как-то делал такое, но подробностей сейчас не вспомню. Посмотрите в этом туториале по фасетному поиску: http://webwash.net/tutorials/intro-search-api-part-1-how-create-search-p.... Там в первой части делается настраивается сервер и делается текстовое поле для поиска по содержимому.

by sotkom on ср, 12/11/2014 - 08:37

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

by Mika on вт, 16/12/2014 - 16:38

Добрый день!

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

by DreamR1der on вт, 16/12/2014 - 21:09

Честно говоря не сталкивался с таким, так что не могу ничего посоветовать...

by Дмитрий on вт, 03/02/2015 - 16:53

Может просто запретить вывод "пустых" фацетов? Т.е. если выбрали родителя, то теперь в следующем фильтре не используемые должны отвалиться сами, т.е. в их выборку не попадает ничего и он не показываются.
В глобальный настройках фасета должно стоять "Minimum facet count" - 1,
Это не то?

Добавить комментарий

Filtered HTML

  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешённые HTML-теги: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.