/
Laravel scout 로 elastic search 사용하기

Laravel scout 로 elastic search 사용하기

laravel 5.3 에 도입된 scout 패키지를 사용하여 full text search engine 연계하는 방법에 대해 설명합니다.


설치

  1. scout elastic search 패키지를 설치합니다.

    laravel 6.x
    $ composer require babenkoivan/scout-elasticsearch-driver
    laravel 5.8
    $ composer require babenkoivan/scout-elasticsearch-driver "^3.0"

    만약 ES 6을 사용한다면 3.12 버전을 설치해 줍니다.

  2. config/app.php 의 providers 에 프로바이더를 추가합니다. 개인적으로는 Laravel 의 Package Discovery 기능을 별로 좋아하지 않아서 직접 추가해 주는데 등록해 주지 않아도 최신 버전의 라라벨에서는 정상 동작합니다.

    'providers' => [
        Laravel\Scout\ScoutServiceProvider::class,
        ScoutElastic\ScoutElasticServiceProvider::class,
    ]
  3. config에 설정 파일을 생성하기 위해 vendor publish 수행합니다.

    php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
    php artisan vendor:publish --provider="ScoutElastic\ScoutElasticServiceProvider"
  4. 컨피그 파일(config/scout_elastic.php) 설정 변경이 필요하면 수정합니다.
  5. .env 에 다음 내용을 추가합니다.

    SCOUT_DRIVER=elastic
    
    ## laravel scout host
    SCOUT_ELASTIC_HOST=localhost:80
    • nginx 를 붙여서 사용할 경우 SCOUT_ELASTIC_HOST 에 포트를 명시해야 합니다.(기본 9200)
    • URL 뒤에 trailing slash(Ex: my.site:80/) 를 붙이면 오작동하므로 주의하세요!
  6. Queue 를 사용하여 인덱싱할 경우 config/scout.php 의 다음 항목을 true 로 설정합니다.

    'queue' => true,

Index configurator

모델별로 index 를 생성해 줘야 하며 다음 명령어로 인덱스 설정 클래스를 생성할 수 있습니다.

관례상 클래스 이름은 "모델명 + IndexConfigurator" 로 지으면 되며 아래는 Users 테이블용 index configurator 를 생성합니다.

php artisan make:index-configurator UserIndexConfigurator
UserIndexConfigurator
<?php

namespace App;

use ScoutElastic\IndexConfigurator;
use ScoutElastic\Migratable;

class UserIndexConfigurator extends IndexConfigurator
{
    use Migratable;

    // index 이름을 직접 설정하려면 $name 변수에 이름을 지정해 주면 됩니다.
    // 생략할 경우 `IndexConfigurator` 를 제외한 snaked class 이름으로 생성됩니다.
    protected $name = 'user_index';

    // You can specify any settings you want, for example, analyzers.
     protected $settings = [
        'analysis' => [
            "tokenizer" => [
                "nori_user_dict" => [
                    "type" => "nori_tokenizer",
                    "decompound_mode" => "mixed",
                    "user_dictionary" => "userdict_ko.txt"
                ]
            ],
            'analyzer' => [
                'my_analyzer' => [
                    'type' => 'custom',
                    "tokenizer" => "nori_user_dict"
                ]
            ]
        ]
    ];

    // ES field 매핑
    protected $defaultMapping = [
        'properties' => [
            "id"=> [
                "type"=> "long"
            ],
            "name"=> [
                "type"=> "text",
                "analyzer"=> "my_analyzer",
                "search_analyzer"=> "my_analyzer"
            ],
            "email"=> [
                "type"=> "text",
                "analyzer"=> "my_analyzer",
                "search_analyzer"=> "my_analyzer"
            ],
            "created_at"=> [
                "type"=> "date"
            ],
            "updated_at"=> [
                "type"=> "date"
            ],
        ] // properties
    ];
}


이제 인덱스를 생성해 줍니다. 만약 Mapping 이 달라지면 update-index 명령을 실행해야 합니다.

$ art elastic:create-index "App\UserIndexConfigurator"

The my_index index was created!
The my_index_write alias for the my_index index was created!



localhost:9200/my_index 에 연결해서 인덱스가 생겼는지 확인해 봅니다.


검색 가능하게 Model 모델 설정

Model class 와 ES 연동은 간단하게 Searchable trait 을 추가하고 $indexConfigurator 변수에 사용할 IndexConfigurator 만 등록해 주면 됩니다.

주의할 점은 Searchable trait 은 Laravel\Scout\Searchable 이 아닌 ScoutElastic\Searchable 을 사용해야 합니다. 


<?php

class MyModel extends Model
{
	 // Laravel\Scout\Searchable을 사용하지 않도록 주의
     use \ScoutElastic\Searchable; 

	 // 사용할 index
     protected $indexConfigurator = MyIndexConfigurator::class;


indexing

Batch indexing

scout:import artisan 명령으로 모델 데이타를 배치로 인덱싱할 수 있습니다.

$ php artisan scout:import "App\MyModel"


Record 추가

Searchable 트레이트를 추가한 모델은  save() 메서드 호출시 자동으로 인덱싱됩니다.

$order = new App\Order;

// ...

$order->save();


또는 명시적으로 searchable() 메서드를 호출하면 인덱싱이 됩니다.

// Adding via Eloquent query...
App\Order::where('price', '>', 100)->searchable();

// You may also add records via relationships...
$user->orders()->searchable();

// You may also add records via collections...
$orders->searchable();


테스트 데이타 생성

실제 테스트를 위해 Faker 로 Model factory 를 생성하고 indexing 해 보겠습니다.


  1. 테스트용 테이블을 만들기 위한 새로운 migration 생성합니다.

    $ php artisan make:migration --table=company add_company_on_users_table
  2. User 테이블에 컬럼을 추가합니다.

    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('company', 50);
            $table->string('address', 100);
            $table->string('phoneNumber', 50);
        });
    }
     
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('company');
            $table->dropColumn('address');
            $table->dropColumn('phoneNumber');
        });
    }
  3. migration 실행합니다.

    $ php artisan migrate
  4. database/factories/ModelFactory.php 수정합니다.

    $factory->define(App\User::class, function (Faker\Generator $faker) {
        static $password;
    
        // 한글 로캘 적용된 Faker 팩토리 생성
        $koFaker = \Faker\Factory::create('ko_KR');
    
        return [
            'name' => $koFaker->name,
            'company' => $koFaker->company,
            'address' => $koFaker->address,
            'phoneNumber' => $koFaker->phoneNumber,
            'email' => $faker->unique()->companyEmail,
            'password' => $password ?: $password = bcrypt('secret'),
            'remember_token' => str_random(10),
        ];
    });
  5. 팅커 구동

    $ php artisan tinker
  6. 테스트용 모델 팩토리 생성

    >>> factory('App\User', 300)->create();
  7. 검색

    >>> $us = App\User::search('민')->get();

검색(Searching)

기본 검색

모델의 search() 메소드 사용

>>> $us = App\User::search('민형')->get();


Where 구문 사용

>>> $us = App\User::search('민형')->where('name', '용훈')->get();


Ref

See also

Related content

Laravel Scout 으로 MeiliSearch 연동하기
Laravel Scout 으로 MeiliSearch 연동하기
More like this
PhpStorm 으로 라라벨 개발 하기
PhpStorm 으로 라라벨 개발 하기
More like this
spatie tags library 로 laravel app 에 tag 붙이기
spatie tags library 로 laravel app 에 tag 붙이기
More like this
Laravel doctrine ORM
Laravel doctrine ORM
More like this
PHPStan 의 laravel 용 wrapper 인 larastan 사용하기
PHPStan 의 laravel 용 wrapper 인 larastan 사용하기
More like this
laravel nova search relationship
laravel nova search relationship
More like this