0

Series Laravel & Elasticsearch Thực chiến #1: Triệu hồi "Quái vật" và Cú bắt tay đầu tiên

1. Tại sao MySQL khóc thét còn Elasticsearch thì cười?

MySQL được sinh ra để lưu trữ dữ liệu có tính toàn vẹn và quan hệ (Relational). Khi tìm kiếm văn bản hoặc chuỗi, nó thường phải quét qua từng dòng.

Trong khi đó, Elasticsearch là một Search Engine dựa trên nền tảng Apache Lucene. Nó không dùng bảng (Table) mà dùng Chỉ mục (Index). Sức mạnh của nó nằm ở cơ chế Inverted Index (Chỉ mục đảo ngược) — giống hệt như phần mục lục ở cuối một cuốn sách dày. Thay vì lật từng trang để tìm chữ "Giao dịch lỗi", ES lật mục lục và biết ngay chữ đó nằm ở trang 15, 102 và 305.

Tốc độ phản hồi của ES cho các tập dữ liệu hàng chục triệu dòng được tính bằng mili-giây (ms).

2. Triệu hồi Elasticsearch vào trận đồ Docker

Trước khi code Laravel, chúng ta cần một con server ES đang chạy. Tận dụng kiến thức Docker ở series trước, bạn chỉ cần mở file docker-compose.yml của dự án và nạp thêm khối này vào:

# Container Elasticsearch
  elasticsearch:
    image: elasticsearch:8.10.2
    container_name: laravel_es
    restart: unless-stopped
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false # Tắt bảo mật để dễ học ở môi trường Local
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # Giới hạn RAM để máy không bị đơ
    ports:
      - "9200:9200"
    volumes:
      - es_data:/usr/share/elasticsearch/data
    networks:
      - laravel_network

# Thêm volume ở cuối file
volumes:
  es_data:

Sau khi thêm xong, bạn chạy lệnh docker-compose up -d. Để kiểm tra xem "quái vật" đã thức giấc chưa, hãy mở trình duyệt và truy cập http://localhost:9200. Nếu thấy một chuỗi JSON trả về dòng chữ "You Know, for Search", bạn đã thành công!

3. Trang bị vũ khí cho Laravel

Mở Terminal và dùng container PHP của chúng ta để cài đặt thư viện chính thức của Elasticsearch dành cho PHP.

docker-compose exec app composer require elasticsearch/elasticsearch

Tiếp theo, bạn mở file .env của Laravel và thêm cấu hình tọa độ kết nối:

# Lưu ý: Chúng ta dùng tên container 'elasticsearch' thay vì 'localhost'
ELASTICSEARCH_HOST=elasticsearch:9200

4. Cú bắt tay đầu tiên (Khởi tạo Connection)

Thay vì gọi trực tiếp class Elasticsearch lộn xộn ở khắp các Controller, tư duy chuẩn Backend Enterprise là chúng ta sẽ đăng ký nó như một Service dùng chung (Singleton) trong Laravel thông qua AppServiceProvider.

Bạn mở file app/Providers/AppServiceProvider.php và thêm đoạn code sau vào hàm register():

namespace App\Providers;

use Elastic\Elasticsearch\ClientBuilder;
use Elastic\Elasticsearch\Client;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        // Bind class Client vào Service Container
        $this->app->singleton(Client::class, function ($app) {
            return ClientBuilder::create()
                ->setHosts([env('ELASTICSEARCH_HOST', 'localhost:9200')])
                ->build();
        });
    }

    public function boot(): void
    {
        //
    }
}

5. Viết lệnh Ping kiểm tra (Artisan Command)

Để chứng minh code Laravel đã kết nối được với ES, cách ngầu nhất là tự viết một lệnh Artisan. Chạy lệnh tạo Command:

docker-compose exec app php artisan make:command ElasticPing

Mở file vừa được tạo ra tại app/Console/Commands/ElasticPing.php và cập nhật logic:

namespace App\Console\Commands;

use Elastic\Elasticsearch\Client;
use Illuminate\Console\Command;

class ElasticPing extends Command
{
    protected $signature = 'elastic:ping';
    protected $description = 'Kiểm tra kết nối đến cụm Elasticsearch';

    public function handle(Client $client)
    {
        $this->info('Đang gửi tín hiệu đến Elasticsearch...');

        try {
            // Lấy thông tin cơ bản của cụm ES
            $response = $client->info();
            $version = $response['version']['number'];
            $clusterName = $response['cluster_name'];

            $this->info("✅ Kết nối THÀNH CÔNG!");
            $this->line("🔥 Cluster: " . $clusterName);
            $this->line("🚀 Phiên bản: " . $version);
            
        } catch (\Exception $e) {
            $this->error("❌ Kết nối THẤT BẠI: " . $e->getMessage());
        }
    }
}

Thực thi: Bạn quay lại Terminal và gõ:

docker-compose exec app php artisan elastic:ping

All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.