Tìm hiểu Elasticsearch với laravel

Giới thiệu về ElasticSearch trong php

Nếu bạn chưa đọc bài viết Tìm hiểu về Elastic Search cơ bản thì bạn có thể đọc lại nó để hiểu hơn về ElasticSearch là gì bạn nhé. Về cơ bản:

  • Elasticsearch là một search engine.

  • Elasticsearch được xây dựng để hoạt động như một server cloud theo cơ chế của RESTful.

  • Kế thừa và phát triển từ Lucene Apache.

  • Phát triển bằng ngôn ngữ java.

Như vậy ta có thể hiểu nôm na ElasticSearch là 1 engine hỗ trợ search sử dụng như 1 server và khi ta muốn thêm, sửa, xóa dữ liệu thì ta sẽ dùng curl để connect đến server ElasticSearch thông qua cổng 9200. Về cấu trúc của ElasticSearch thì ta có thể hiểu như sau (so sánh với SQL):

Giới thiệu về Elastic Search trong php

Trong SQL ta có các cơ sở dữ liệu với các bảng chứa cấu trúc của dữ liệu (các cột) và các row dữ liệu. Chuyển cấu trúc đó so sánh với ElasticSearch thì ta có Indexes (giống các Database trong DBMS) và bên trong Indexes ta có Types (giống Table trong DBMS) và ta cũng có Documents giống như các bản ghi trong SQL. Trong Document chứa các field tương ứng với các thuộc tính của Document đó. Như vậy cũng đủ hiểu sơ qua về ElasticSearch rồi bây giờ chúng ta sẽ đi tìm hiểu chi tiết các cài đặt và ứng dụng vào với project Laravel.

Cài đặt ElasticSearch trên Centos 7

Bước 1 - Cài đặt Java Trước tiên.

Bạn sẽ cần Môi trường chạy thi hành Java (JRE) trên Giọt của bạn vì Elaticsearch được viết bằng ngôn ngữ lập trình Java.

Bạn có thể sử dụng gói CentOS OpenJDK riêng cho JRE. JRE này miễn phí, được hỗ trợ tốt và được quản lý tự động thông qua trình quản lý cài đặt CentOS Yum. Bạn có thể cài đặt OpenJDK mới nhất bằng lệnh:

sudo yum install java-1.8.0-openjdk.x86_64

Để xác minh JRE của bạn đã được cài đặt và có thể được sử dụng, hãy chạy lệnh:

java -version

Kết quả sẽ như thế này:

openjdk version "1.8.0_65"
OpenJDK Runtime Environment (build 1.8.0_65-b17)
OpenJDK 64-Bit Server VM (build 25.65-b01, mixed mode)

Bước 2 - Tải xuống và cài đặt Elaticsearch

Có thể tải xuống Elaticsearch trực tiếp từ thun.co trong các gói zip, tar.gz, deb hoặc vòng / phút. Đối với CentOS, tốt nhất là sử dụng gói vòng / phút gốc sẽ cài đặt mọi thứ bạn cần để chạy Elaticsearch.

Tại thời điểm viết bài này, phiên bản Elaticsearch mới nhất là 1.7.3. Tải xuống trong thư mục bạn chọn bằng lệnh:
wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.3.noarch.rpm

Sau đó cài đặt nó theo cách CentOS thông thường với lệnh vòng / phút như thế này:

sudo rpm -ivh elasticsearch-1.7.3.noarch.rpm

Điều này dẫn đến việc Elaticsearch được cài đặt trong /usr/share/elasticsearch/ với các tệp cấu hình của nó được đặt trong /etc/elasticsearch và tập lệnh init của nó được thêm vào /etc/init.d/elasticsearch.

Để đảm bảo Elaticsearch bắt đầu và dừng tự động với Giọt, hãy thêm tập lệnh init của nó vào các đường chạy mặc định bằng lệnh:

sudo systemctl enable elasticsearch.service

Sử dụng ElasticSearch for PHP

ElasticSearch cung cấp sẵn thư viện dành cho PHP tại địa chỉ này https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html

Sử dụng ElasticSearch for PHP

Để cài đặt ta chỉ cần sử dụng composer:

composer require elasticsearch/elasticsearch

Một vài ví dụ khi sử dụng:

use Elasticsearch\ClientBuilder;

$client = ClientBuilder::create()->build();

// Index a document
$params = [
    'index' => 'my_index',
    'type' => 'my_type',
    'id' => 'my_id',
    'body' => ['testField' => 'abc']
];

$response = $client->index($params);
print_r($response);

// Search for a document
$params = [
    'index' => 'my_index',
    'type' => 'my_type',
    'body' => [
        'query' => [
            'match' => [
                'testField' => 'abc'
            ]
        ]
    ]
];

$response = $client->search($params);
print_r($response);

Nôm na là tạo một biến $client để gửi các request thực hiện các yêu cầu đến server ElasticSearch và nhận kết quả.

Tích hợp với Laravel Eloquent Model

Để kết hợp ElasticSearch với Laravel có rất nhiều packages có thể làm được. Ví dụ như: PlasticElasticsearch Eloquentelasticsearcher,... Nhưng trong phạm vi bài viết này mình sẽ giới thiệu package Elasicquent. Đây là 1 package giúp chúng ta làm việc với ElasticSearch và Eloquent một cách dễ dàng hơn. Ta có thể tạo index và tìm kiếm ngay trong Eloquent Model.

Ta có thể cài đặt dễ dàng qua composer:

composer require elasticquent/elasticquent

Thêm providers và aliases:

'providers' => [
    ...
    Elasticquent\ElasticquentServiceProvider::class,
],
'aliases' => [
    ...
    'Es' => Elasticquent\ElasticquentElasticsearchFacade::class,
],

Thêm ElasticquentTrait vào Model mà bạn muốn sử dụng để index với ElasticSearch.

use Elasticquent\ElasticquentTrait;

class Book extends Eloquent
{
    use ElasticquentTrait;
}

Elasticsearch Configuration: 

php artisan vendor:publish --provider="Elasticquent\ElasticquentServiceProvider"
<?php

return array(

    /*
    |--------------------------------------------------------------------------
    | Custom Elasticsearch Client Configuration
    |--------------------------------------------------------------------------
    |
    | This array will be passed to the Elasticsearch client.
    | See configuration options here:
    |
    | http://www.elasticsearch.org/guide/en/elasticsearch/client/php-api/current/_configuration.html
    */

    'config' => [
        'hosts'     => ['localhost:9200'],
        'retries'   => 1,
    ],

    /*
    |--------------------------------------------------------------------------
    | Default Index Name
    |--------------------------------------------------------------------------
    |
    | This is the index name that Elastiquent will use for all
    | Elastiquent models.
    */

    'default_index' => 'my_custom_index_name',

);

Demo với Laravel

Để thực hiện demo với Laravel ta tạo model và data để test như sau:

php artisan make:model Post -m
// Post.php

class Post extends Model
{
    protected $fillable = [
        'title', 
        'body', 
        'tags'
    ];
}
<?php

// PostTableSeeder.php

use Illuminate\Database\Seeder;
use App\Article;

class PostTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = Faker\Factory::create();

        for($i=0; $i<50; $i++) {
          Post::create([
            'title' => $faker->sentence(3),
            'body' => $faker->paragraph(6),
          ]);
        }
    }
}

Sau khi chạy seed ta đã có một bảng dữ liệu cơ bản để test. Tiếp theo ta sẽ setup Elasticquent trong model Post:

<?php

// Post.php

namespace App;
use Elasticquent\ElasticquentTrait;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use ElasticquentTrait;

    protected $fillable = ['title', 'body', 'tags'];

    protected $mappingProperties = array(
        'title' => [
          'type' => 'text',
          'analyzer' => 'standard',
        ],
        'body' => [
          'type' => 'text',
          'analyzer' => 'standard',
        ],
      );
}

Các thuộc tính trong $mappingProperties chính là các trường cần đánh index. Và kiểu analyzer = stanard chính là việc tự động tách từ theo space trong quá trình phân tích dữ liệu đưa vào đánh index. Và bây giờ để đánh index cho Post ta dùng tinker và chạy command

App\Post::addAllToIndex();

Sau khi đã add vào index ta có thể kiểm tra bằng cách truy cập localhost:9200/ten_index với tên index chính là tên đã setup trong file config/elasticquent.php nếu ra kết quả thì có nghĩa là đã thêm index thành công. Bây giờ ta thử search theo ElasticSearch nhé:

Route::get('search-es', function () {
    $response = \App\Post::searchByQuery([
        'match' => [
            'title' => 'Illo'
        ]
    ]);

    return dd($response);
});

Kết quả như sau:  Như vậy ta search theo title match với chữ "Illo" cho ra 3 kết quả. Ngoài ra còn nhiều hàm nữa của Elasticquent các bạn có thể xem thêm ở đây.

Kết luận

Như vậy mình vừa giới thiệu đến các bạn cách tích hợp và sử dụng ElasticSearch trong PHP. Bài này là cơ bản nhất để bắt đầu với ElasticSearch. Còn rất nhiều thứ của ElasticSearch mà mình chưa thể trình bày hết ở đây. Các bạn có thể tìm hiểu thêm.