12/08/2018, 14:45

Sử dụng Elasticsearch trong Laravel

Cách đây vài tháng, mình có xây dựng một website thương mại điện tử và tất nhiên như mọi trang web khác thì mình phải xây dựng chức năng tìm kiếm.Tìm kiếm là chức năng vô cùng quan trọng, ảnh hưởng đến trải nghiệm người dùng, tuy nhiên hầu hết chúng ta đều xem nó là một task đơn giản và cài đặt ...

Cách đây vài tháng, mình có xây dựng một website thương mại điện tử và tất nhiên như mọi trang web khác thì mình phải xây dựng chức năng tìm kiếm.Tìm kiếm là chức năng vô cùng quan trọng, ảnh hưởng đến trải nghiệm người dùng, tuy nhiên hầu hết chúng ta đều xem nó là một task đơn giản và cài đặt chức năng này theo cách đơn giản là chỉ sử dụng query với like.Với cách làm này thì bạn đã biết kết quả rồi đấy, chức năng tìm kiếm của chúng ta khá cùi bắp.Thật may mắn, mình được một đứa bạn suggest một search engine để apply vào, đó là Elasticsearch.Mình cũng mất kha khá thời gian để tìm hiểu về search engine này.Hiểu đơn giản thì Elasticsearch là một document oriented database, nhiệm vụ của nó là lưu trữ và triệu gọi document.Tất cả các documents được hiển thị dưới dụng Json. Elasticsearch cho phép phân tích và tìm kiếm dữ liệu theo thời gian thực, nó có performance rất tốt, dễ dàng áp dụng và triển khai một cách hiệu quả vào các nguồn dữ liệu khác nhau. Để tìm hiểu kỷ hơn về Elasticsearch thì bạn có thể đọc link này. Trong bài viết này mình sẽ hướng dẫn các bạn tích hợp search engine này với Laravel.

Bước 1: Cài đặt Elasticsearch

Ở bước đầu tiên này bạn sẽ cài đặt Elasticsearch trên máy của mình.Nếu bạn chưa cài đặt thì có thể làm theo hướng dẫn trên trang chủ của Elasticsearch để cài đặt. Nếu bạn đang làm việc với Ubuntu thì bạn có thể dễ dàng cài đặt theo link này.

Bước 2: Cài đặt Package

Ở bước này, chúng ta sẽ cài đặt gói elasticquent/elasticquent để sử dụng Elasticsearch API Link github. Bạn thêm dòng sau vào file composer.json rồi chạy lệnh "composer update"

"elasticquent/elasticquent": "dev-master"

Bạn mở file config/app và thêm path và alias như bên dưới:

return [
    ......
    'provides' => [
        ......
        ......,
        ElasticquentElasticquentServiceProvider::class,
    ],
    'aliases' => [
        ......
        ......,
        'Es' => ElasticquentElasticquentElasticsearchFacade::class,
    ],
]

Bây giờ bạn cần sinh file cấu hình cho Elasticsearch bằng việc chạy lệnh bên dưới:

php artisan vendor:publish --provider="ElasticquentElasticquentServiceProvider"

Bước 3: Tạo table items và model

Ở bước này chúng ta sẽ tạo migrate cho bảng items sử dụng artisan command.Bạn chạy lệnh bên dưới:

php artisan make:migration create_items_table

Sau khi tạo thành công thì bạn vào thư mục database/migrations và thêm đoạn code sau vào để tạo bảng items.

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreateItemsTable extends Migration
{

    public function up()
    {
        Schema::create('items', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('description');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop("items");
    }
}

Sau khi tạo bảng items thành công thì bạn sẽ tạo model Item. Bạn vào thư mục app và tạo file Item với nội dung như bên dưới:

namespace App;

use IlluminateDatabaseEloquentModel;
use ElasticquentElasticquentTrait;

class Item extends Model
{
    use ElasticquentTrait;

    public $fillable = ['title','description'];

}

Bước 4: Route và Controller

Ở bước này thì bạn phải thêm route vào file routes như bên dưới:

Route::get('ItemSearch', 'ItemSearchController@index');
Route::post('ItemSearchCreate', 'ItemSearchController@create');

OK, bây giờ bạn sẽ tạo một ItemSearchController trong thư mục app/Http/Controllers.

namespace AppHttpControllers;

use IlluminateHttpRequest;
use AppHttpRequests;
use AppItem;

class ItemSearchController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return IlluminateHttpResponse
     */
    public function index(Request $request)
    {
        if($request->has('search')){
            $items = Item::search($request->input('search'))->toArray();
        }
        return view('ItemSearch',compact('items'));
    }

    /**
     * Display a listing of the resource.
     *
     * @return IlluminateHttpResponse
     */
    public function create(Request $request)
    {
        $this->validate($request, [
            'title' => 'required',
            'description' => 'required',
        ]);

        $item = Item::create($request->all());
        $item->addToIndex();

        return redirect()->back();
    }
}

Trong file này chúng ta sẽ xữ lý việc tìm kiếm và trả về kết quả.

Bước 5: Tạo View

Ở bước cuối cùng này thì bạn phải tạo một view để hiển thị kết quả.Bạn tạo file ItemSearch.blade.php với nội dung như sau:

@extends('layouts.app')

@section('content')
<div class="row">
<div class="col-md-8 col-md-offset-2">
    <h1 class="text-primary" style="text-align: center;">Laravel 5 Search Using Elasticsearch</h1>
</div>
</div>

<div class="container">
<div class="panel panel-primary">
  <div class="panel-heading">
    <div class="row">
      <div class="col-lg-6">
        {!! Form::open(array('method'=>'get','class'=>')) !!}
        <div class="input-group">

          <input name="search" value="{{ old('search') }}" type="text" class="form-control" placeholder="Search for...">
          <span class="input-group-btn">
            <button class="btn btn-default" type="submit">Go!</button>
          </span>

        </div> 
        {!! Form::close() !!}
      </div> 
    </div> 
  </div>
  <div class="panel-body">


        <div class="row">
            <div class="col-lg-6">
                @if(!empty($items))
                    @foreach($items as $key => $value)
                        <h3 class="text-danger">{{ $value['title'] }}</h3>
                        <p>{{ $value['description'] }}</p>
                    @endforeach
                @endif
            </div>
            <div class="col-lg-6">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        Create New Items
                    </div>
                    <div class="panel-body">

                        @if (count($errors) > 0)
                            <div class="alert alert-danger">
                                <strong>Whoops!</strong> There were some problems with your input.<br><br>
                                <ul>
                                    @foreach ($errors->all() as $error)
                                        <li>{{ $error }}</li>
                                    @endforeach
                                </ul>
                            </div>
                        @endif

                        {!! Form::open(array('url' => 'ItemSearchCreate','autocomplete'=>'off')) !!}
                            <div class="row">
                                <div class="col-xs-12 col-sm-12 col-md-12">
                                    <div class="form-group">
                                        <strong>Title:</strong>
                                        {!! Form::text('title', null, array('placeholder' => 'Title','class' => 'form-control')) !!}
                                    </div>
                                </div>
                                <div class="col-xs-12 col-sm-12 col-md-12">
                                    <div class="form-group">
                                        <strong>Description:</strong>
                                        {!! Form::textarea('description', null, array('placeholder' => 'Description','class' => 'form-control','style'=>'height:100px')) !!}
                                    </div>
                                </div>
                            </div>

                            <div class="text-center">
                                <button type="submit" class="btn btn-primary">Submit</button>
                            </div>

                        {!! Form::close() !!}

                    </div>
                </div>
            </div>
        </div>

  </div>
</div>
</div>
@endsection

Bây giờ thì bạn có thể check trong project của mình để xem thành quả đạt được rồi.Hi vọng với bài hướng dẫn này thì các bạn có thể apply vào project Laravel của mình để xây dựng chức năng tìm kiếm nhanh chóng và mạnh mẽ hơn.

[Link tham khảo] [1] https://www.elastic.co/downloads/elasticsearch [2] https://laravel-news.com/laravel-and-elasticsearch

0