Lập trình PHP

Phần này trình bày cách sử dụng elasticsearch-php là thư viện để PHP kết nối làm việc với Elasticsearch.

Cài đặt elasticsearch-php

Nên sử dụng Composer để cài đặt elasticsearch-php, gõ lệnh sau:
composer require  "elasticsearch/elasticsearch"
Sau khi thư viện đã tích hợp vào dự án, các file PHP độc lập muốn nạp thư viện này sử cần thêm vào đoạn mã
require 'vendor/autoload.php';
Như vậy đã sẵn sàng để dùng elasticsearch-php, cũng chú ý là PHP cần có extension ext-curl (xem thêm sử dụng curl với php)

Cấu hình kết nối PHP tới Elasticsearch

Đối tượng dùng để kết nối tương tác với ES sinh ra từ lớp Elasticsearch/Client, có có được nó có thể dùng công cụ ClientBuilder với dữ liệu cầu hình kết nối. Ví dụ:

//Cấu hình kết nối đến ES
$hosts = [
    [
        'host' => 'localhost',          //yourdomain.com
        'port' => '9200',
        'scheme' => 'http',             //https
//        'path' => '/elastic',
//        'user' => 'username',         //nếu ES cần user/pass
//        'pass' => 'password!#$?*abc'
    ],

];
//Tạo đối tượng Client
$client = ClientBuilder::create()
    ->setHosts($hosts)
    ->build();

Sau khi có $client thì bắt đầu có thể sử dụng nó để thực hiện các thao tác trên ES như: search, update, delete ..., sau đây là một số thao tác sau khi có $client

Tạo / xóa một Index

Ví dụ cần tạo một ES index đặt tên là article

$params = [
    'index' => 'article'
];


//Kiểm tra xem Index đã tồn tại không
$indexExist = $client->indices()->exists($params);

if (!$indexExist) {
    try {
        //Thực hiện tạo Index
        $response = $client->indices()->create($params);


    }
    catch (Exception $e) {
        //Lỗi tạo Index
        $res = json_decode($e->getMessage());
        echo $res->error->reason;
    }
}
else {
    echo "Index {$params['index']} đã có rồi!";
}

Nếu muốn xóa một Index thì thực hiện như sau:

$params = [
    'index' => 'article'
];


//Kiểm tra xem Index đã tồn tại không
$indexExist = $client->indices()->exists($params);

if ($indexExist) {
    $response = $client->indices()->delete($params);
    echo "Đã xóa";
}
else {
    echo "Index {$params['index']} không có";
}

Chỉ mục, cập nhật, xóa Document

Chỉ mục (tạo, cập nhật) một Document
$params = [
    'index' => 'article',                       //Index lưu Document
    'id' => '1',                                //Nếu thiếu id thì ID tự sinh
    'type' => 'article_type',
    //'timestamp' => time(),                    // Thiết lập timestamp nếu cần thiết
    'body' => [ 'testkey' => 'testvalue']       //Dữ liệu Document
];

$response = $client->index($params); 
Lập chỉ mục nhiều Document
$params = [
  'body' => [
      [ 'index' => ['_index' => 'article',  '_type' => 'article_type', ] ],
      [ 'testkey1' => 'value1', 'testkey2' => 'testkey2'],

      [ 'index' => ['_index' => 'article',  '_type' => 'article_type', ] ],
      [ 'testkey1' => 'value11', 'testkey2' => 'testkey22']

    ]
];

$responses = $client->bulk($params);
Đọc một Document từ Index
$params = [
    'index' => 'article',
    'type' => 'article_type',
    'id' => '1'
];

$response = $client->get($params);
Cập nhật Document
$params = [
    'index' => 'article',
    'type' => 'article_type',
    'id' => '1',
    'body' => [
        'doc' => [
            'testkey1' => 'valueabc',
            'new_field' => 'abc'
        ]
    ]
];

$response = $client->update($params);
Xóa một Document trong Index
$params = [
'index' => 'article',
'type' => 'article_type',
'id' => '1'
];

$response = $client->delete($params);

Tìm kiếm với ES

Tìm kiếm với match query
$params = [
    'index' => 'article',
    'type' => 'article_type',
    'body' => [
        'query' => [
            'match' => [
                'testkey' => 'testvalue'
            ]
        ]
    ]
];

$results = $client->search($params);
Tìm kiếm phức tạp hơn với logic should, must ...
$params = [
    'index' => 'article',
    'type' => 'article_type',
    'body' => [
        'query' => [
            'bool' => [
                'filter' => [
                    'term' => [ 'testkey1' => 'abc' ]
                ],
                'should' => [
                    ['match' => [ 'testkey1' => 'value1' ]],
                    ['match' => [ 'testkey2' => 'value2' ]]
                ]
            ]
        ]
    ]
];


$results = $client->search($params);

Kỹ thuật scroll để lấy hết kết quả tìm kiếm

Kỹ thuật scroll giống như sử dụng con trỏ cursor trong truy vấn CSDL SQLServer - một cách để paging dữ liệu. Ở phần trên,
$client->search($params) nó trả về tập kết quả - và chỉ lấy được kết quả với số lượng document mặc định là 10 hoặc chỉ ra trong tham số size (nhưng lớn nhất là 10000 document). Lúc này nếu sử dụng scroll bạn sẽ lấy thêm được các kết quả vượt qua size (page khác). Cách thực hành như sau:

Truy vấn đầu tiên, thiết lập cho nó thêm một tham số là scroll gán bằng khoảng thời gian giữ cho con trỏ tìm kiếm tồn tại, ví dụ 30 giây 30s, 3 phút là 3m. Nếu có tham số này thì kết quả truy vấn đầu tiên sẽ trả về, có kèm một một tham số là id của con trỏ _scroll_id - nó trỏ đến dòng kết quả của ngữ cảnh tìm kiếm hiện tại. Từ con trỏ này, yêu cầu lấy các giá trị tiếp theo

$params = [
    'index' => 'article',
    'type' => 'article_type',
    'scroll' => '1m',           // Giữ con trỏ tìm kiếm tồn tại 1m để truy vấn trang tiếp theo
    'size' => 10000,            // mỗi trang 1000 kết quả
    'body' => [
        'query' => [
            'match' => [
                'testkey' => 'testvalue'
            ]
        ]
    ]
];

$response   = $client->search($params);           // Truy vấn đầu tiên

while (isset($response['hits']['hits']) && count($response['hits']['hits']) > 0) {

    // **
    // Viết code xử lý kết quả  trả về (đọc) - foreach ($rs['hits']['hits'] as $r)
    // **

    // Khi hoàn thành, lấy scroll_id để lấy kết quả trang tiếp (như 10000 kết quả tiếp theo)
    $scroll_id = $response['_scroll_id'];

    // Thực hiện cuộn tới kết quả tiếp theo
    $response = $client->scroll([
            'scroll_id' => $scroll_id,
            'scroll'    => '30s'  // thiết lập con trỏ tồn tại tiếp 30s
        ]
    );
}

Mã nguồn tham khảo: elasticsearch-learning

Đăng ký theo dõi ủng hộ kênh