С выходом Scout 9 появился стандартный драйвер для MeiliSearch в Laravel. В связи с чем немного изменилась установка и настройка поиска по сайту.
Установка и настройка MeiliSearch
Для тестирования поиска устанавливал MeiliSearch в Windows. Для это достаточно зайти на страницу проекта в GitHub и найти последнюю сборку, файл с именем meilisearch-windows-amd64.exe
или как-то похоже. Скачать и запустить. Собственно все.
Для установки на Linux (у меня Ubuntu), в командной строке:
echo "deb [trusted=yes] https://apt.fury.io/meilisearch/ /" > /etc/apt/sources.list.d/fury.list
apt update && apt install meilisearch-http
Чтобы каждый раз не запускать движок вручную сделаем его сервисом, для этого создадим файл:
sudo nano /etc/systemd/system/meilisearch.service
Скопируем текст в файл, задав свой мастер-ключ:
[Unit]
Description=MeiliSearch
After=systemd-user-sessions.service
[Service]
Type=simple
ExecStart=/usr/bin/meilisearch --http-addr 127.0.0.1:7700 --env production --master-key masterKey
[Install]
WantedBy=default.target
Запускаем и убеждаемся, что все работает:
systemctl enable meilisearch
systemctl start meilisearch
systemctl status meilisearch
Установка не занимает много времени, а на сайте MeiliSearch можно найти актуальные инструкции.
Установка и настройка Scout в Laravel
Для работы с поиском необходим стандартный модуль Laravel Scout. Установим его в проект с помощью composer:
composer require laravel/scout
Публикуем конфигурацию:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
Устанавливаем SDK MeiliSearch:
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
В .env добавляем настройки:
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey
Добавление поиска в модель
Для добавления в поиск информации необходимо настроить модель в Laravel. На примере модели Blog:
use Laravel\Scout\Searchable;
class Blog extends Model
{
use Searchable; // Обязательно добавляем трейт Searchable
// При желании прописываем имя индекса. Лучше прописать, если есть сомнения.
public function searchableAs()
{
return 'blog';
}
// Настраиваем список полей, которые будут индексироваться
// Лучше прописать, а то будет индексировать все
public function toSearchableArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'teaser' => $this->teaser,
'body' => $this->body,
'comments' => $this->comments->implode('comment', '; '),
];
}
// Если модель по каким-то причинам не надо включать в поиск, задаем тут:
public function shouldBeSearchable()
{
return $this->public;
}
Индексирование и поиск
Руками создавать индекс в MeiliSearch не обязательно, достаточно выполнить команду:
php artisan scout:import "App\Models\Blog"
После чего все модели проиндексируются. Переиндексация происходит автоматически при обновлении, создании и удалении модели. Поиск по модели осуществляется с помощью функции search($text)
. Приведу пример ендпоинта в контроллере, который осуществляет поиск:
public function search(Request $request)
{
$text = $request->get('query');
$blogs = Blog::search($text)->take(20)->get();
return view('page.search', ['blogs' => $blogs, 'query' => $text]);
}
Фильтры в поиске
Если вы планируете использовать конструкцию where
или whereIn
необходимо вручную создать фильтр в MeiliSearch. Иначе будет вылезть ошибка вида:
Attribute `xxx` is not filterable. Available filterable attributes are: ``.
Фильтры создаются через обращение к API напрямую, например, curl:
curl \
-X PATCH 'http://localhost:7700/indexes/blog/settings' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer masterKey' \
--data-binary '{
"filterableAttributes": [
"xxx"
]
}'
Тут надо заменить xxx
, на имя своего атрибута. Также можно создавать фильтр с помощью PHP:
use MeiliSearch\Client;
$client = new Client('http://127.0.0.1:7700', 'masterKey');
$client->index('blog')->updateFilterableAttributes(['public']);
Обратите внимание, что фильтр создается только один раз. Пример использования фильтра:
$blogs = Blog::search($text)->where('public', 1)->get();
Лишних фильтров лучше не плодить, они занимают много места.
Пагинация результатов поиска
Поиск поддерживает стандартную пагинацию:
$blogs = Blog::search($text)->paginate(20);
В шаблоне страницы добавляем:
{{ $blogs->links() }}
Резюме
MeiliSearch хорошо работает с русским языком. Учитывает склонения, прощает ошибки и опечатки. MeiliSearch шустро работает, хотя при первом запуске может конкретно загрузить систему на несколько часов индексацией. В целом резульаты поиска весьма релевантны, оценить поиск можно на этом сайте. Можно рекомендовать MeiliSearch как поисковый движок для небольших и средних проектов. Его можно быстро установить и настроить, он не требователен к ресурсам и выдает хорошие результаты.