Laravel та Elasticsearch: підключення та базове налаштування пошуку
14 Липня 2021
У цій статті ділимося одним з наших кейсів, підключення і використання Elasticsearch разом з Laravel на одному з наших проектів (інформація про переваги в порівнянні з конкурентами, і що це за новий проект, буде в одному з наступних постів).
Стаття ділиться на дві частини:
1. Підключення Elasticsearch до Laravel і реалізація простого повнотекстового пошуку з урахуванням друкарських помилок. Базове налаштування, мапінг, індексація даних і простий запит, який поверне результати з урахуванням помилок.
2. Агрегація даних або як його називали в 6-й версії Elasticsearch - фасетний пошук. Його часто можна побачити у фільтрах e-commerce проектів, а саме у підрахунку кількості товарів при фільтрації.
1. Підключення та базове налаштування Elasticsearch
Технології та версії
Ми завжди використовуємо найактуальніше та найсвіжіше, що є на даний момент, на момент написання статті – це:
- Laravel 8,
- PHP 8,
- Elasticsearch 7,
- Mysql 8,
- Apache2.
Вибір пакету
Laravel пропонує просте рішення для реалізації повнотекстового пошуку по Eloquent моделям Scout, який використовує власний обсерватор для автоматичної переіндексації даних при зміні/додаванні/видаленні даних з таблиці. Рішення хороше, однак, Scout не підтримує еластичнийвиробництво з коробки (зараз, у версії laravel8, підтримується тільки Algolia і MeiliSearch) і він не дає такої гнучкості, яка потрібна для більш складних рішень, наприклад, як агрегація даних у фільтрах. Ну і «магія» Laravel зі Scout не дає повного розуміння, як працювати з пошуком та налаштовувати його.
Тому, виходячи з вищезазначеного, вибір упав на пакет, який надає самий еластик: «elasticsearch/elasticsearch »
Індексація даних
Процес налаштування сервера, установки Laravel, Elasticsearch на сервер, налаштування БД і заповнення таблиці тестовими даними, за якою будемо налаштовувати пошук, упущу, думаю це не повинно бути проблемою.
Пропишемо для початку в конфізі services хост для еластика:
Шукатимемо в таблиці products по полю заголовка, поле title у таблиці, тип поля varchar. Для цього я створив заздалегідь 1 млн. записів у таблиці, спеціально так багато, щоб показати відмінності у швидкості пошуку з використанням elasticsearch від стандартного mysql like, якщо в таблиці буде велика кількість даних.
У AppServiceProvider забиндімо клас клієнта з Elasticsearch, щоб можна було легко використовувати його в різних класах.
Створимо trait Searchable та observer ElasticsearchObserver для моделі Product, яка стежитиме за оновленнями даних та оновлюватиме індекс.
Trait Searchable виглядатиме приблизно так:
observer ElasticsearchObserver:
Створимо ще консольну команду класу ReindexProduct, щоб проіндексувати всі записи з таблиці products, і записати їх до Elasticsearch:
У методі handle видаляємо індекс якщо він вже є, створюємо новий індекс з налаштуваннями для індексації, і записуємо кожен товар в еластик.
Налаштування для індексації – важливий момент!
Для гнучкого налаштування пошуку під ваші потреби, в них можна описати mappings (це як типи даних у mysql) і analysis, де ми описуємо, як саме еластик має обробляти наш запит. Analysis іMappings - це окрема велика тема в еластиці, детальніше можна почитати в офіційній документації, але для базового прикладу підійде і цей варіант налаштувань.
Все готово, запустимо команду індексації:
Після того, як проіндексуються всі записи, а для індексації 1 млн. записів доведеться зачекати, можна налаштувати логіку коду для пошуку.
Логіка пошуку
Створимо контролер, який прийматиме запит, передаватиме його на сервіс пошуку, де буде основна логіка, і повертатиме "в'юху" з потрібними нам даними:
Сервіс буде виглядати приблизно так:
Elasticsearch вже повертає результат за релевантністю, у методі buildCollection беремо всі id записів, і сортуємо їх у запиті в тому ж порядку, як повернув еластик.
Після всього виконаного, сторінка результату пошуку буде виглядати приблизно так:
Як видно на скріншоті, в результаті пошуку ми отримали різні варіанти записів, де є слово «вітаміни» з урахуванням помилок та різних закінчень слів.
Швидкість виконання такого запиту буде десь 80-150 мілісекунд:
А тепер замінимо у нашому контролі пошук з еластика на класичний title like ‘%вітаміни%’ та подивимося швидкість такого запиту:
82 секунди!!! Багато, і ні одна нормальна людина не буде чекати результатів пошуку, ну і сам результат буде без урахування помилок.
PS. Це була реалізація базового пошуку, так би мовити «Elastic для чайників».
У наступній статті розглянемо агрегацію даних, що дуже важливо для будь-якого e-commerce проекту.
Статтю підготував: Артур Щаблевський
Сподобалася стаття ? - Поділіться посиланням ::