Если ваш сайт на PHP начал тормозить при поиске по тысячам записей, значит, пора выходить на новый уровень. Встроенный поиск в MySQL — это как искать иголку в стоге сена с лупой. Elasticsearch — это мощный поисковый движок, который делает это за миллисекунды. В этой статье я расскажу, как подключить его к PHP, чтобы ваш проект летал, а пользователи находили нужное мгновенно.
Что такое Elasticsearch и зачем он нужен
Elasticsearch — это поисковый сервер, который хранит данные в виде JSON-документов и умеет быстро их искать. Представьте, что у вас есть огромная библиотека, а библиотекарь — это Elasticsearch. Вы говорите ему: «Найди все книги про космос», — и он мгновенно приносит нужные тома. При этом он не просто ищет точные совпадения, а понимает, что «космос» и «звёзды» связаны.
В PHP мы общаемся с Elasticsearch через HTTP-запросы. Можно использовать официальный клиент, а можно просто отправлять JSON-запросы через cURL. Второй вариант проще для понимания, поэтому начнём с него.
Установка и первое подключение
Сначала нужно установить Elasticsearch. Это можно сделать локально или на сервере. Для разработки достаточно скачать архив с официального сайта и запустить. После этого убедимся, что он работает, открыв в браузере http://localhost:9200. Если видите JSON с информацией о версии — всё отлично.
Теперь напишем простой PHP-скрипт, который проверит подключение:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:9200');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo 'Версия Elasticsearch: ' . $data['version']['number'];
Этот код отправляет GET-запрос к серверу и выводит версию. Если всё работает, вы увидите что-то вроде «Версия Elasticsearch: 8.11.0».
Создаём индекс и добавляем данные
В Elasticsearch данные хранятся в индексах. Индекс — это как таблица в MySQL, только умнее. Создадим индекс для статей блога:
$indexName = 'articles';
$mapping = [
'mappings' => [
'properties' => [
'title' => ['type' => 'text'],
'content' => ['type' => 'text'],
'author' => ['type' => 'keyword'],
'views' => ['type' => 'integer']
]
]
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:9200/' . $indexName);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($mapping));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
var_dump($response);
Здесь мы создали индекс articles с полями: title (текст), content (текст), author (ключевое слово) и views (целое число). Тип text означает, что поле будет полнотекстово искать, а keyword — для точного совпадения.
Теперь добавим несколько документов:
$documents = [
[
'title' => 'Как выучить PHP',
'content' => 'PHP — это просто, если практиковаться каждый день.',
'author' => 'Иван Петров',
'views' => 1200
],
[
'title' => 'Основы Elasticsearch',
'content' => 'Elasticsearch — это поисковый движок на базе Lucene.',
'author' => 'Мария Сидорова',
'views' => 850
]
];
foreach ($documents as $doc) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:9200/articles/_doc/');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($doc));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
}
Каждый документ получает уникальный ID автоматически. Если нужно свой ID, укажите его в URL: /articles/_doc/my_id.
Поиск по индексу
Теперь самое интересное — поиск. Допустим, пользователь хочет найти статьи про PHP. Отправляем поисковый запрос:
$query = [
'query' => [
'match' => [
'title' => 'PHP'
]
]
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:9200/articles/_search');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($query));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
foreach ($result['hits']['hits'] as $hit) {
echo 'Найдено: ' . $hit['_source']['title'] . ', автор: ' . $hit['_source']['author'] . PHP_EOL;
}
Запрос match ищет слово «PHP» в поле title. Elasticsearch возвращает документы, отсортированные по релевантности. Можно усложнить запрос, добавив фильтры, сортировку или агрегации.
Фильтры и сортировка
Часто нужно искать с условиями. Например, показать статьи автора «Иван Петров» с числом просмотров больше 1000. Используем bool запрос:
$query = [
'query' => [
'bool' => [
'must' => [
['match' => ['content' => 'PHP']]
],
'filter' => [
['term' => ['author' => 'Иван Петров']],
['range' => ['views' => ['gte' => 1000]]]
]
]
],
'sort' => [
'views' => ['order' => 'desc']
]
];
Здесь must — обязательное условие, filter — фильтры, которые не влияют на релевантность, а sort — сортировка по убыванию просмотров.
term вместо match. match разбивает текст на слова и ищет каждое, а term ищет точную фразу без изменений.
Работа с официальным клиентом PHP
Хотя cURL — это просто, для больших проектов лучше использовать официальный клиент elasticsearch/elasticsearch. Установите его через Composer:
composer require elasticsearch/elasticsearch
Теперь подключение и операции выглядят более элегантно:
require 'vendor/autoload.php';
$client = \Elastic\Elasticsearch\ClientBuilder::create()
->setHosts(['http://localhost:9200'])
->build();
// Создание индекса
$params = [
'index' => 'articles',
'body' => [
'mappings' => [
'properties' => [
'title' => ['type' => 'text'],
'content' => ['type' => 'text']
]
]
]
];
$response = $client->indices()->create($params);
// Добавление документа
$params = [
'index' => 'articles',
'id' => '1',
'body' => [
'title' => 'Новая статья',
'content' => 'Содержимое статьи'
]
];
$response = $client->index($params);
// Поиск
$params = [
'index' => 'articles',
'body' => [
'query' => [
'match' => ['title' => 'новая']
]
]
];
$response = $client->search($params);
foreach ($response['hits']['hits'] as $hit) {
echo $hit['_source']['title'];
}
Клиент берёт на себя много рутины: обработку ошибок, переподключение, сериализацию. Это удобно и надёжно.
Практические советы и лайфхаки
Вот несколько вещей, которые сэкономят вам нервы при работе с Elasticsearch:
- Не храните в индексе большие тексты целиком. Лучше хранить только ключевые поля, а остальное брать из основной базы данных.
- Используйте алиасы для индексов. Это позволяет менять структуру индекса без простоя.
- Настройте анализаторы для русского языка. По умолчанию Elasticsearch не понимает морфологию, но есть плагины, которые это исправляют.
- Следите за размером индекса. Если он разрастается, используйте шардирование (разбиение на части).
Сравнение cURL и официального клиента
| Критерий | cURL | Официальный клиент |
|---|---|---|
| Сложность подключения | Низкая | Средняя (нужен Composer) |
| Возможности | Все, но вручную | Все + удобные методы |
| Обработка ошибок | Вручную | Автоматическая |
| Производительность | Хорошая | Отличная (пул соединений) |
Что в итоге
Elasticsearch — это мощный инструмент, который легко интегрируется с PHP. Вы можете начать с простых cURL-запросов, а позже перейти на официальный клиент. Главное — понимать базовые принципы: индексы, документы, запросы. С ними вы сможете построить быстрый и гибкий поиск для любого проекта.
Не бойтесь экспериментировать. Создайте тестовый индекс, добавьте данные, поиграйте с запросами. Через час практики вы почувствуете себя уверенно, а ваш сайт станет заметно шустрее.
Удачи в кодинге!



