Живой поиск на Drupal 7

Сегодня я вам расскажу, как сделать живой поиск на друпал. Для этого нам понадобятся:

Search API
Search API Database Search
Search API pages
Search API live results
Скачиваем и включаем все эти модули вручную или по-нормальному через
drush en search_api search_api_db search_api_page search_api_live_results -y
Затем идём в "Конфигурация - Поиск и метаданные - Search API - Добавить сервер" и заполняем там поля, как показано на картинке ниже. Поле "минимальная длина слова" определяет, после ввода скольких символов будут появляться результаты. Один символ - это насилие над базой данных, а вот 3-5 - в самый раз. Галочка "Искать по частичным совпадениям" означает, что поиск будет вестись по фрагментам слов. Если её не выставить, то результаты будут находиться только по целым словам, что не всегда удобно.
db_server
Теперь, когда у нас есть сервер, можно создать поисковый индекс. Идём аналогично - "Конфигурация - Поиск и метаданные - Search API - Добавить индекс" и заполняем там поля следующим образом: имя - любое вменяемое имя, машинное имя, согласно правилам для машинных имён drupal, "Тип элемента" - тип сущности (материал(нода), термин таксономии и т.д. Тут как правило, имеет смысл выбирать именно материал, если у вас есть например связанные продукты commerce - их поля потом можно будет также добавить. "Наборы" - выбираем те типы материалов, которые собираемся индексировать. Тут важно не забыть никакой тип, но и не ставить галочки туда, куда не надо, чтобы не захламлять базу данных. В поле "Сервер" выбираем наш только что созданный сервер. "Только чтение" - не трогаем, оставляем невыбранным. "Проиндексировать элементы сразу" - выставляем обязательно. Если не выставить, то новые материалы в индексе будут появляться только по крону, если же выставить, то любые изменения будут индексироваться сразу. "Cron batch size" - оставляем, как есть - 50. Это означает, что если есть что-то неиндексированное, то по крону будет индексироваться по 50 элементов. Сорри, что не сделал скрин - он был бы слишком длинный и не очень информативный Smile

После нажатия кнопки сохранить нас перебросит на форму добавления полей в индекс. Я обычно выбираю в добавок ко всему остальному тип материала и ID. Для живого поиска выбираем заголовок и Body. Если у вас есть ещё какие-то важные текстовые поля, выберите и их. Важно: выбирайте для текстовых полей тип Fulltext, т.к. в Fulltext можно производить поиск по фрагментам текста. Однако, Fulltext не позволяет делать сортировку, для этого нужен тип "Строка". Если же вы хотите искать и сортировать по одному и тому же полю, то это можно настроить на вкладке "Фильтры" в настройках поискового индекса, но об этом я расскажу как-нибудь в следующий раз Smile

Если вы ищете в полях Body, не отчаивайтесь. Текст с форматом ввода - это сложносоставное поле, поэтому его нужно добавлять как связанное поле. Да-да, вот там внизу кнопка "Добавить связанные поля". Но прежде чем жать эту кнопку, сохраните форму, иначе внесённые изменения потеряются! Такая вот засада. На этом с поисковым индексом пока всё.

Теперь нам нужна форма поиска для нашего поискового индекса. Стандартная форма нам не подходит, т.к. это вообще другой поиск. К слову, при использовании Search API стандартный модуль поиска Search лучше отключить и анинсталлить. А для формы поиска нам нужен модуль Search API Pages. Идём в "Конфигурация - Поиск и метаданные - Search API - Страницы поиска - Добавить страницу поиска". Там всё просто - вводим заголовок поисковой страницы и её путь, выбираем наш поисковый индекс, остальное по вкусу и согласно здравому смыслу.

И последний шаг - включить живой поиск. Для этого идём на страницу редактирования поискового индекса, заходим на вкладку Live Results и ставим галочку напротив недавно созданной страницы поиска. Сохраняемся. Если нажать "Изменить", то можно задать количество выпадающих результатов и тип отображения - просто кликабельное название либо стиль отображения live results search. К слову, этот стиль отображения полностью настраивается в настройках отображения материала, а также есть шаблон для него, который можно найти в папке модуля. Естественно, для переопределения шаблона надо скопировать его в свою тему.

Форма поиска доступна как блок на странице управления блоками. Также её можно вызвать программно:

$search_page entity_load_single('search_api_page'1);
$search_form drupal_get_form('search_api_page_search_form_search'$search_page);
?>

Поздравляю! Теперь ваш сайт стал чуточку менее колхозным, ведь около 100% разработчиков практически не волнуются о том, как работает окошко поиска на сайте, в результате чего оно не всегда работает в принципе. А если вы сделали всё по инструкции, то у вас должна получиться красота такая же, как на картинке в начале статьи. Ну само собой, что надо ещё немного поверстать, чтобы оно смотрелось как на этой картинке:
Живой поиск

PS: на всякий случай, не надо путать live results и автокомплит, т.к. у них в корне разное поведение. Если по клику на живой результат вы переходите на его страницу, то по клику на вариант из автокомплита этот вариант просто вставляется в окно ввода текста и это логично, ведь автодополнение должно просто помогать вводить данные и ничего более.

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

Автор

Комментарии

Аватар пользователя gun_dose gun_dose 15 ноября 2016 в 23:12
1

Только потому что он даёт форму поиска. И live results заточен под неё. А сама страница поиска легко темизируется - можно настроить, какой режим отображения выводить и есть шаблон страницы, можно, например, повыпиливать вывод некоторых элементов, таких как время выполнения запроса.
Естественно, что под поисковые фильтры нужен вьюс. Тут речь только о текстовом поиске. И выводить те же фасеты на странице текстового поиска смысла нет, т.к. выборка может быть слишком разношёрстная.

Аватар пользователя bumble bumble 16 ноября 2016 в 0:12
1

А вот от меня - отдельное спасибо за search_api_pages!
Как-раз искал варианты работы с Search API без Views.

Аватар пользователя gun_dose gun_dose 16 ноября 2016 в 7:38

Я в таком варианте не понял, как сделать переход по ссылке при клике на вариант - он тупо вставлялся в текстовое окно.

Аватар пользователя gun_dose gun_dose 16 ноября 2016 в 14:45

Да, точно, это на Search API Autocomplete была проблема. Что-то твой сайт подозрительно быстро работает))

Аватар пользователя VasyOK VasyOK 16 ноября 2016 в 14:49

Я ж говорю: там нет Search API. Быстро? Ниче вообще не делал для этого. ДАже не включит то, что должно быть включено в производительности.

Аватар пользователя tooez tooez 16 ноября 2016 в 20:32

У меня после попытки поиска выбивает ошибку:
PDOException: в функции locale() (строка 749 в файле E:\WebSites\site\modules\locale\locale.module).
На сайте произошла непредвиденная ошибка. Пожалуйста, повторите попытку позже.

Поиск работает (вылезают материалы по словам), но если просто ввести слово и нажать "поиск", то выдает страницу с ошибкой выше.

Аватар пользователя gun_dose gun_dose 16 ноября 2016 в 21:15

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

Аватар пользователя tooez tooez 17 ноября 2016 в 6:16
1
gun_dose wrote:

поле язык и в конфигурации страницы поиска

Я тоже это не выбирал - делал, Как у вас написано! Вечером попробую.
Спасибо за статью! И блог у вас здоровский )

Аватар пользователя HardHardy HardHardy 6 декабря 2016 в 15:34

Спасибо за статью!
А не подскажете решение
Пытаюсь вывести программно

<?php
$search_page 
entity_load_single('search_api_page'1);
$search_form drupal_get_form('search_api_page_search_form_search'$search_page);
?>

выдает ошибку

  • Notice: Undefined index: search_api_page_search_form_search в функции drupal_retrieve_form() (строка 807 в файле /var/www/p155471/data/www/site.ru/includes/form.inc).
  • Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'search_api_page_search_form_search' not found or invalid function name в функции drupal_retrieve_form() (строка 842 в файле /var/www/p155471/data/www/site.ru/includes/form.inc).

Что не так?

Аватар пользователя HardHardy HardHardy 6 декабря 2016 в 16:24

Да, все включено, настроено и работает. Кроме программного вывода

Еще при использовании поиска летят ошибки

Strict warning: Only variables should be passed by reference в функции search_api_live_results_json() (строка 23 в файле /var/www/p155471/data/www/site.ru/sites/all/modules/search_api_live_results/includes/search_api_live_results.pages.inc).

Аватар пользователя gun_dose gun_dose 6 декабря 2016 в 16:33

Проверьте тогда машинное имя своей страницы поиска. Там в самом модуле форма вызывается так:

<?php
$block
['content'] = drupal_get_form('search_api_page_search_form_' $page->machine_name$pageNULLTRUE);
?>

А ошибки эти - косяк модуля. Там в render() засунуты функции, а не переменные, если сначала выполнить то, что внутри рендера и передать в него переменную, то будет норм. Не стал искать патчей на такую мелочь и пофиксил сам, хоть это и не комильфо))

Аватар пользователя HardHardy HardHardy 6 декабря 2016 в 18:12

не могу понять
какое машинное имя?
Путь страницы поиска указал - /search_page
В live-results когда изменить тыкаю в адресной строке строке - /search_api_page_1/edit

пробовал в строчку $search_page = entity_load_single('search_api_page', 1); вместо 'search_api_page' подставить search_page или search_api_page_1
у меня сразу фатал еррор
Fatal error: Class name must be a valid object or a string in /var/www/p155471/data/www/site.ru/includes/common.inc on line 8041

Метод тыка на этом у меня исчерпан Smile Cray 2

Аватар пользователя gun_dose gun_dose 6 декабря 2016 в 18:29
1

Значит, попробуйте так

<?php
$search_page 
entity_load_single('search_api_page'1);
$search_form drupal_get_form('search_api_page_search_form_search_page'$search_page);
?>

Всё просто - у меня путь поисковой страницы search а у вас search_page.

Аватар пользователя HardHardy HardHardy 6 декабря 2016 в 19:56

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

В общем вывел блок таким образом

<?php
$block 
block_load("search_api_page""search");
$render_array _block_get_renderable_array(_block_render_blocks(array($block)));
echo 
render($render_array);
?>

Спасибо большое за помощь!!!

Аватар пользователя gun_dose gun_dose 6 декабря 2016 в 20:17
1

Можно и так, просто я решил взять саму форму без обёрток. На трёх сайтах сработало. Тут ещё такой момент, что после экспериментов может оказаться, что айдишник сущности у страницы поиска не 1, а 2 или 3. Я, чтобы написать те две строки кода, изрядно порылся в базе и в коде модуля.

Аватар пользователя tooez tooez 16 марта 2017 в 10:15

Живой поиск работает, спасибо.
Одно понять не могу - если я пишу в поиск запрос, то вылезают нужные страницы, но если я нажимаю "найти", то страница поиска пустая.
Как это пофиксить?

Аватар пользователя Boozenok Boozenok 18 апреля 2017 в 21:46

Подскажите, а если у меня есть товары с вариацией и у каждого товара есть свой артикул. Я хочу сделать поиск по названию и по артикулу. Если использовать для поиска ноды (одна нода-один товары), то тут все просто. А вот как лучше быть с вариациями товара? К примеру по названию еще можно, но как лучше организовать по артикулу, что бы срабатывал поиск как автокомплит, отсеивая неподходящие варианты.

Спасибо

Аватар пользователя gun_dose gun_dose 18 апреля 2017 в 22:13

Надо добавить в поисковый индекс артикул товара, как поле fulltext. И вроде бы поставить галочку в настройках поисковой страницы.

Аватар пользователя Boozenok Boozenok 18 апреля 2017 в 23:04

нет, так не помогает. оно ищет артикул, например, 13-1-0001 по всем товарам, но не отсеивается ненужные товары. Также если делать поиск по товару - не подтягивается view mode (((

Есть еще идеи?

Аватар пользователя gun_dose gun_dose 19 апреля 2017 в 7:47

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

Аватар пользователя void void 10 августа 2017 в 23:54

gun_dose, не подскажите как заменить заголовок страницы поиска, созданной с помощью Search API pages с дефолтного, который прописывается в настройке созданной страницы на заголовок типа "Результат поиска по запросу <[ЗАПРОС]>"?

Аватар пользователя void void 11 августа 2017 в 9:19

Вроде то, что надо. Вроде смотрел шаблоны, но проглядел. drupal_set_title меняет (из шаблона) метатег title, а вот сам заголовок h1 почему-то не меняет.

Аватар пользователя gun_dose gun_dose 11 августа 2017 в 9:57
1

Да, обычно заголовок страниц задаётся другими способами, причём везде по-разному. Сказать по правде, нет времени вникать, что там и как устроено, но в качестве временного решения можно поставить в page.tpl.php условие, чтобы не выводить заголовок на странице поиска, а в шаблоне результатов поиска h2 заменить на h1.

Аватар пользователя Phantom63rus Phantom63rus 6 апреля 2018 в 3:00

Полезная статья!

Я правильно понимаю, что сортировку результатов нужно делать через вьюс? Или есть вариант обойтись без тяжёлой артиллерии?

Аватар пользователя gun_dose gun_dose 6 апреля 2018 в 6:50

Тут же вьюс не используется, поэтому сортировки тупо нет)) сам удивился, когда увидел, что при одном и том же запросе последовательность результатов может быть разной. Надо погуглить issues к Search API Pages, может быть есть патчи. Чутьё подсказывает, что решается это парой строк кода.

Аватар пользователя Phantom63rus Phantom63rus 6 апреля 2018 в 11:20

Ну там есть модуль для интеграции...

Собсна у меня задача простая:
1. Все вхождения в заголовках и сортировка по дате создания.
2. По текстами и опять же сортировка по дате.

И специфика такова что без такой сортировки живой поиск по бесполезности не отличается от стокового:)

Аватар пользователя gun_dose gun_dose 6 апреля 2018 в 12:31

А что за модуль для интеграции? Можно ссылочку?

По поводу бесполезности - тут фишка в выпадающих результатах, т.е. сугубо UX аспект. То есть, планируется, что пользователь введёт в поиск запрос, по которому будет штук 5 результатов, и не будет надобности переходить на страницу поиска.

Аватар пользователя Phantom63rus Phantom63rus 6 апреля 2018 в 14:36

Хз, не включал ещё, в списке модулей значится как search_api_views, он вроде в комплекте.

Сделал сортировку по дате при помощи https://www.drupal.org/project/search_api_sorts - но это не совсем то. Оно может отсортировать, но именно что безусловно отсортировать, все критерии и их веса идут лесом.

Фактически то что получается можно вообще реализовать через вьюс без всяких дополнительных поисковых движков, это таки не совсем то что нужно. А мне бы в идеале дату загнать как один из параметров с высоким весом...

Аватар пользователя gun_dose gun_dose 6 апреля 2018 в 14:38

search_api_views тут не подходит, т.к. search_api_live_results использует search_api_pages, который, в свою очередь, работает без вьюсов.

Аватар пользователя Phantom63rus Phantom63rus 6 апреля 2018 в 15:07

Да и не надо, как бы в критерии сортировки дату добавить? Что-то у меня гуглятся решения для solr, но для моего проекта это мягко скажем избыточно.

Аватар пользователя Phantom63rus Phantom63rus 6 апреля 2018 в 17:32

Насилие над гуглом и яндексом показало что... барабанная дробь... ни в гугле ни в яндексе этот функционал нормально не реализован! @#$%^!

Аватар пользователя VasyOK VasyOK 10 апреля 2018 в 0:34

Можно вопрос. А Search API live results без views работает? Если без Search API pages страницу поиска создать на views? то как?

https://www.drupal.org/project/search_api_live_results/issues/1392650 - тут вроде патч какой-то написали 6 лет назад. Пишут что патч в последней dev. Не вижу, чтобы он был там. Если честно и не знаю, что там должно быть.

Аватар пользователя gun_dose gun_dose 10 апреля 2018 в 7:04

Да, работает без вьюс. Чтобы создать страницу через вьюс, нужна простая вьюха по индексу с раскрытым фильтром по какому-то текстовому полю. Как потом это пристаканить к live results - хз. Но вьюха с раскрытым фильтром будет искать по одному полю, а search api page при вводе текста в окошко ищет его сразу во всех проиндексированных текстовых полях.

Аватар пользователя Phantom63rus Phantom63rus 10 апреля 2018 в 11:49

Фильтр комбинированных полей, стоковый функционал. Я побоялся пробовать на своём проекте:)

Аватар пользователя Phantom63rus Phantom63rus 10 апреля 2018 в 14:57

Поиск можно сделать через views. Если нужно сделать по разным полям - можно использовать поиск по комбинированным полям. Прикинув какое это будет изнасилование БД я решил не пробовать даже.

Аватар пользователя bumble bumble 10 апреля 2018 в 15:06

Но, только @gun_dose не про фильтр комбинированных полей, а про раскрытый фильтр по индексной вьюхе.

Аватар пользователя VasyOK VasyOK 10 апреля 2018 в 15:03
Phantom63rus wrote:

можно использовать поиск по комбинированным полям

Создао вьюху для поискового индекса, добавил туда раскрытый фильтр Поиск. Вы про это?
Если да, то как туда live results всунуть? Если нет, то про что?

Аватар пользователя VasyOK VasyOK 10 апреля 2018 в 21:58

Как поиск через views я знаю. Я звел речь про так live results к views приделать.