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

Digital-студия WNDER

Зачем Elasticsearch в Yii?

Yii — отличный фреймворк, но его встроенные возможности поиска по базе данных (например, через LIKE) не всегда эффективны. Elasticsearch — это поисковый движок, который умеет быстро находить нужное даже в миллионах записей. Он анализирует текст, учитывает опечатки, синонимы и релевантность. В Yii есть официальное расширение yiisoft/yii2-elasticsearch, которое упрощает интеграцию.

Представьте, что у вас интернет-магазин с тысячами товаров. Пользователь вводит «красная футболка». Elasticsearch найдёт все футболки красного цвета, даже если в описании написано «алый» или «бордовый». Согласитесь, это круто.

Установка и настройка

Сначала установим Elasticsearch. Скачайте его с официального сайта и запустите. Для разработки хватит и локальной установки. Затем добавьте расширение в ваш Yii-проект через Composer:

composer require --prefer-dist yiisoft/yii2-elasticsearch

После установки настройте компонент в конфиге приложения (обычно config/web.php):

return [
    'components' => [
        'elasticsearch' => [
            'class' => 'yii\elasticsearch\Connection',
            'hosts' => [
                'http://localhost:9200',
            ],
        ],
    ],
];

Теперь Yii знает, где искать Elasticsearch. По умолчанию он слушает порт 9200.

Индексация данных

Чтобы искать, нужно проиндексировать данные. Elasticsearch хранит документы в индексах. Проще всего связать модель Yii с индексом. Допустим, у нас есть модель Product с полями id, name, description. Создадим для неё поисковый класс, унаследованный от yii\elasticsearch\ActiveRecord:

namespace app\models;

use yii\elasticsearch\ActiveRecord;

class ProductIndex extends ActiveRecord
{
    public static function index()
    {
        return 'products';
    }

    public static function type()
    {
        return 'product';
    }

    public function attributes()
    {
        return ['id', 'name', 'description'];
    }
}

Теперь можно заполнять индекс данными из базы. Например, после сохранения модели Product вызывайте индексацию:

$product = new ProductIndex();
$product->id = $model->id;
$product->name = $model->name;
$product->description = $model->description;
$product->save();

Для массовой индексации используйте цикл или специальные команды. Но будьте осторожны: Elasticsearch не любит частых мелких запросов. Лучше индексировать пакетами.

Правило: Всегда индексируйте данные после изменения в базе. Можно использовать события модели Yii (например, afterSave), чтобы автоматически обновлять индекс.

Поиск и запросы

Когда данные проиндексированы, можно искать. Простейший запрос — полнотекстовый поиск по всем полям:

$query = ProductIndex::find()->query([
    'multi_match' => [
        'query' => 'красная футболка',
        'fields' => ['name', 'description'],
    ],
]);
$results = $query->all();

Этот запрос найдёт документы, где встречаются слова «красная» и «футболка». Elasticsearch автоматически анализирует текст: приводит к нижнему регистру, удаляет стоп-слова и т.д. Вы можете настроить анализаторы для более точного поиска.

Для сложных запросов используйте yii\elasticsearch\Query. Например, поиск с фильтром по цене:

$query = ProductIndex::find()
    ->query([
        'bool' => [
            'must' => [
                'multi_match' => [
                    'query' => 'футболка',
                    'fields' => ['name', 'description'],
                ],
            ],
            'filter' => [
                'range' => [
                    'price' => ['gte' => 1000, 'lte' => 5000],
                ],
            ],
        ],
    ]);

Обратите внимание: для фильтрации по цене поле price должно быть в индексе. Добавьте его в attributes().

Практические советы и лайфхаки

Вот несколько проверенных приёмов, которые сэкономят вам время и нервы:

  • Используйте пакетную индексацию. Если данных много, индексируйте порциями по 500-1000 документов. Это снизит нагрузку.
  • Настройте маппинг. По умолчанию Elasticsearch сам определяет типы полей. Но лучше явно указать маппинг для строковых полей (например, text для полнотекстового поиска, keyword для точного совпадения).
  • Кэшируйте результаты. Если поиск повторяется, используйте кэш Yii. Это ускорит ответ.
  • Мониторьте производительность. Следите за размером индекса и скоростью запросов. Elasticsearch имеет встроенные инструменты мониторинга.

Сравним основные параметры подключения Elasticsearch в Yii:

Параметр Описание Пример значения
hosts Список хостов Elasticsearch ['http://localhost:9200']
index Имя индекса по умолчанию 'products'
type Тип документа (устарел в новых версиях) 'product'
analyzer Анализатор текста 'standard'

Ещё один лайфхак: используйте yii\elasticsearch\Query::highlight() для подсветки найденных фрагментов в результатах. Это улучшает пользовательский опыт.

Совет: Если вы только начинаете, не пытайтесь сразу настроить сложные анализаторы и маппинги. Начните с простого поиска, а затем улучшайте.

Что в итоге?

Интеграция Yii с Elasticsearch — это мощный способ сделать поиск на сайте быстрым и релевантным. Вы настроили подключение, научились индексировать данные и выполнять запросы. Теперь ваш поиск будет работать как швейцарские часы. Главное — не забывайте обновлять индекс при изменении данных и следите за производительностью.

Попробуйте внедрить Elasticsearch в свой проект, начните с малого, и вы увидите, как оживёт поиск. Удачи!

Студия WNDER