일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- MacOS
- mac
- MYSQL
- ubuntu
- PostgreSQL
- Laravel
- FCM
- https
- nginx
- AWS
- node
- php
- 안드로이드
- Android
- 해시키
- selenium
- Passport
- Vue
- SSH
- Vue.js
- pip
- Cordova
- Prometheus
- flutter
- window
- python
- alb
- 파이썬
- 구글 API
- OAuth
- Today
- Total
print( sjw.iq == 200) output : true
[Laravel] Full Text Search (Laravel Scout, Algolia) 본문
안녕하세요!
오늘은 Full Text Search 관련 포스팅을 하려고 합니다~!
서비스를 진행할 때 보통 like 검색으로만 search를 하고
full text search는 추후에 생각하고 있었습니다...
그리고 laravel-scout 를 만나기 전에는 elastic search를 사용한 적이 있었어요!
그런데 저의 문제일 수도 있었지만... 검색결과와 속도가 그리 만족스럽지 않았습니다...
그러다가 이번에 시간이 나서 Laravel Scout 와 Algolia 를 찾아봤는데요...!
일단 결론부터 말씀드리면 검색 속도와 검색 결과가 매우 만족도가 높았습니다!!
설치
먼저 Composer 패키지 관리자를 통해 Scout를 설치합니다.
composer require laravel/scout
그리고 scout config 를 구성합니다.
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
위의 명령어를 실행하고 나면 다음과 같이 config 폴더 밑에 scout 관련 config 파일이 생성된 것을 보실 수 있습니다.
큐작업
기본적으로 큐작업이 true로 되어있습니다! 어플리케이션의 성능을 위해서는 queue를 사용하는게 거의 필수라고 보여집니다!!!
config/scout.php 파일 안에 보시면 아래와 같이 default 값이 true로 되어 있는 것을 볼 수 있습니다.
'queue' => env('SCOUT_QUEUE', true),
검색 가능 모델 및 동기화 유지
새로 insert 되거나 update 되는 데이터들을 동기화를 유지 시켜야만 합니다! 그래야 새로 등록된 값이나 변경된 값도 검색이 잘 되겠죠?
아래와 같이 use Searchable; 을 사용하여 동기화를 유지 시켜줍니다!!!
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
}
#주의할점
대용량 할당은 동기화가 진행되지 않는다!
완전 대용량일 경우는 사용자가 직접 처리해주거나 스케줄러를 돌리는 등의 작업이 필요할 것 같습니다!
www.algolia.com/doc/framework-integration/laravel/indexing/import-into-algolia/?language=php
자 이제 Algolia 드라이버를 설정해보겠습니다!
우선 Algolia PHP SDK 를 설치해줍니다!
composer require algolia/algoliasearch-client-php
그리고 나서 algolia 홈페이지에서 회원가입을 진행하시고 아래 이미지에서 API keys를 클릭해줍니다!
그리고 나면 다음과 같은 화면을 볼 수 있습니다.
Application Id 와 Admin API Key가 필요한데요~!
config/scout.php 파일에 제일 아래에 보시면
'algolia' => [
'id' => env('ALGOLIA_APP_ID', ''),
'secret' => env('ALGOLIA_SECRET', ''),
],
위와 같이 키들을 설정하는 부분이 있습니다!
env에 설정해 주시면 됩니다!
다음은 모델의 인덱스 구성을 해야 하는데요!
table 명이 sjwiq200 인 경우 algolia 사이트에서 sjwiq200인 인덱스를 생성해 줘야 합니다!
모델의 인덱스를 지정할수도 있는데요!
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* Get the index name for the model.
*
* @return string
*/
public function searchableAs()
{
return 'zzieut_sjwiq200';
}
}
위의 코드와 같이 searchableAs 에 인덱스 명을 alias 해주시면 됩니다.
처음부터 해당 구조를 잡고 가시는 분들도 있으시겠지만...
저희는 기존에 데이터가 있는 상태입니다!
기존에 저희 DB에 데이터가 있다고 해서 Algolia가 해당 데이터를 알고 있지는 않겠죠??
그러면 해당 모델들을 algolia에 레코드를 import 시켜주어야 합니다!
몇가지 방법이 있었던 거 같은데
저는 다음 방법이 제일 간단하고 효율적으로 보였습니다!
아래의 코드로 기존에 해당 모델에 있는 데이터들을 모두 import 시킬 수 있습니다.
php artisan scout:import "App\Models\Post"
인덱싱 되어있는 레코드들을 지우기 위해서는 flush 명령을 사용하면 됩니다.
php artisan scout:flush "App\Models\Post"
데이터들을 다음과 같이 import 시켜주시면 algoria에 import 되는 것을 지켜보실 수 있습니다.
검색 가능한 데이터 구성
모델에 데이터들 중에 검색에 필요없는 값들이 있을 수도 있습니다!
그리고 Algolia에는 레코드당 크기 제한이 있기 때문에 필요한 데이터만 인덱싱 하는 것이 좋다고 합니다!
해당 모델 table에서 다음과 같은 메서드를 구현해주시면 됩니다!
public function toSearchableArray()
{
$array = $this->toArray();
return array(
'review_no' => $array['review_no'],
'text' => $array['text'],
'user_id' => $array['user_id'],
);
}
이렇게 되면 review_no, text, user_id 의 데이터만 인덱싱을 합니다!
Relationships
Algolia doesn’t do any JOIN operations. All searchable data must exist in each record.
algolia는 join을 허용하지 않는다고 되어 있는데요!
해당 작업 때문에 애를 좀 먹었습니다!
검색 가능한 데이터가 모두 레코드 안에 들어가 있어야 된다고 하네요!
laravel 에서는 관계를 우선 명시해 주어야 해요!
컨텐츠와 리뷰가 1:n의 관계를 가지고 있다고 하겠습니다!
그럼 해당 모델에 대한 코드를 먼저 살펴보겠습니다!
우선 Contens.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Contents extends Model
{
use Searchable;
protected $table = 'contents';
protected $primaryKey = 'content_no';
public function toSearchableArray()
{
$array = $this->toArray();
return array(
'content_no' => $array['content_no'],
'title' => $array['title'],
'subject' => $array['subject'],
'overview' => $array['overview']
);
}
}
그리고 Reviews.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Reviews extends Model
{
use Searchable;
protected $table = 'reviews';
protected $primaryKey = 'review_no';
public function toSearchableArray()
{
$array = $this->toArray();
$array['contents'] = $this->contents->toArray();
return array(
'review_no' => $array['review_no'],
'content_id' => $array['content_id'],
'review_id' => $array['review_id'],
'addr' => $array['addr'],
'text' => $array['text'],
'tags' => $array['tags'],
'user_id' => $array['user_id'],
'contents' => $array['contents']
);
}
public function contents() {
return $this->belongsTo(Contents::class, 'content_no', 'content_no');
}
}
Reviews.php 쪽만 봐주시면 될 것 같습니다.
Contents 모델에서 $this->hasMany() 로 관계를 명시해줘도 되지만 저는 리뷰 검색을 더 활용할 예정이라
Reviews 모델에서 $this->belongsTo()로 관계를 명시했습니다.
그리고 toSearchableArray 메서드에서 위와 같이 선언을 해주면 컨텐츠 정보가 algoria의 리뷰 indice 에 포함이 됩니다!
Searching
검색하는 방법은 쉽습니다!
해당 모델에 search 메서드를 사용하면 됩니다!
기본적으로 where 조건문이나 laravel에서 지원하는 paginate 같은 기능을 사용할 수 있습니다!
#join 관련해서는 허용을 하지 않아서 위에 인덱싱 하는 부분에 설명이 있습니다.1
$reviews = Reviews::search("관악구 맛집")->paginate(20);
데이터 4만개 정도의 제대로 가공하지 않은 데이터로 5번 정도 날려봤을때 평균 800ms 정도의 시간이 나오는 것 같습니다!!
앞에서 말한바 있지만 전에 elastic search를 썼을때보다 속도와 검색 결과면에서 너무나 만족스러웠습니다!!!
아래의 기업들이 algoria를 쓰고 있는데요! 더 신뢰가 가는 것 같습니다!
매번 가지고 있던 문제를 해결한 것 같아 기분이 좋네요 ㅎㅎㅎ
감사합니다!
# 참고
'PHP' 카테고리의 다른 글
[Laravel] Window 에서 Scheduling 적용하기 (0) | 2021.03.26 |
---|---|
[PHP] MacOS php 버전 올리기 (0) | 2021.01.08 |
[Laravel Secure] Laravel Debug Hide env (0) | 2020.08.27 |
[PHP]POST max upload size 조정 (0) | 2020.08.12 |
[MacOS + Apache + PHP] 설정하기 (0) | 2020.07.27 |