Lalavel ScoutでAlgoliaを使って全文検索を実装してみた！

<h1>やること</h1>
全文検索機能を実装してみる
<h1>環境</h1>
Laravel 5.8
<h1>目次</h1>
1.Algoliaってなんぞやという話
2.LaravelでAlgoliaを使う準備
3.検索テストするためのダミーデータ作成+Algoliaにデータ追加
4.実際に検索する！

<h1>Algoliaってなんぞやという話</h1>
Algoriaは全文検索エンジンのサービスで、人気が高まってる。
ホームページ→ https://www.algolia.com/
緯度経度データ登録すれば位置情報検索も簡単に実装できるみたいです。また今回はLaravelで実装しますが他の言語・フレームワークでも自由に使えるっぽい。

ここのDocumentationから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454650/1b7b58f8-12ba-e8af-4def-b6ef860893ab.png)

API REFERENCEで選択できますよ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454650/4fc94e10-0f79-708f-e363-503a1476da30.png)

サイト内のどこに何があるかわかりにくいですがそこがわかれば各々の説明はとても親切だと思います。
<h1>LaravelでAlgoliaを使う準備</h1>
まず以下のコマンドでScoutをインストールします。

```
composer require laravel/scout
```
これでScoutが使えるようになります。ScoutについてはLaravel公式ドキュメントに詳しく書いてあります。
次に以下のコマンドでconfigディレクトリ内に`scout.php`を作ります。

```
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
```
次に`scout.php`に

```
'queue' => true,
```
を追加してキューの設定を行います。

次に、Algoliaのアカウントを作成し、APIキーとシークレットキーを得ます。
ちなみに初回トライアル無料期間は14日間で、その後は毎月お金がかかってしまいます。。。また、無料期間はレコード数の最大数も少なくなっています。(フリーだと1万件、月額だとプランによって変わってきます。詳しくは公式サイトで)

筆者は会社の隣の席の人にキーを借りているので作成方法とかはわからないですごめんなさい()

そしてキーを生成したら`.env`ファイルに以下を追加してください。

```
ALGOLIA_APP_ID=生成したAPIキー
ALGOLIA_SECRET=生成したシークレットキー
```
最後にAlgolia PHP SDKを以下のコマンドでインストールして準備完了。

```
composer require algolia/algoliasearch-client-php:^2.2
```
<h1>検索テストするためのダミーデータ作成+Algoliaにデータ追加</h1>
まず、検索がちゃんと動くかの確認のためにダミーデータをFakerを使って作ります。
まずターミナルから以下のコマンドでFakerを使えるようにしておきます。

```
composer require fzaninotto/faker
```
今回はpeopleテーブルを作成することにします。ということで、ターミナルで

```
php artisan make:migration create_people_table
php artisan make:seed PeopleTableSeeder
php artisan make:factory PersonFactory
```
database/factories以下に`PersonFactory.php`ができているので以下のように変更します。

```PersonFactory.php
<?php

/* @var $factory \Illuminate\Database\Eloquent\Factory */

use App\Model;
use Faker\Generator as Faker;


$factory->define(App\Person::class, function (Faker $faker) {
    return [
        'last_name' => $faker->lastName,
        'first_name' => $faker->firstName,
        'company' => $faker->company,
        'location' => $faker->city,
        'birth_year' => $faker->year,
        'birth_month' => $faker->month,
    ];
});
```
次にシーダーファイルを以下のように変更

```PeopleTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class PeopleTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(App\Person::class, 1000)->create();
    }
}

```
1000のところは作成するダミーデータの数なのでお好みで〜

最後に`DatabaseSeeder.php`を以下のようにして、

```DatabaseSeeder.php

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(PeopleTableSeeder::class);
    }
}
```

シーディングじゃ！

```
php artisan db:seed
```
ここまでやるとデータベースのpeopleテーブルに１０００件ダミーデータが入ってると思います。

次にこのデータをAlgoriaの方に渡して全文検索ができるようにします。
まずPersonモデルを作っておきます。

```
php artisan make:model PersonModel
```

そしてモデルを以下のように変更します。

```Person.php
<?php

namespace App;

use Laravel\Scout\Searchable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;

class Person extends Model
{
    use Searchable;
    use Notifiable;

    public function searchableAs()
    {
        return 'people_index';
    }

    public function toSearchableArray()
    {
        $array = $this->toArray();

        $array = $this->transform($array);


        return $array;
    }

}
```

searchableAsメソッドに追加した`'people_index'`によってAlgolia側にpeopleというテーブル(?)が作成されます。

```
public function searchableAs()
    {
        return 'people_index';
    }
```
toSearchableArrayメソッドにはどのようなデータを追加するのかが記述されています。
Laravelの公式ドキュメントには記述がなかったのですが、toSearchableArrayにはwhereやwhereBetweenで必要なnumeric valueが定義されてないので、このような処理を行いたい場合には`$array = $this->transform($array);`を追加してデータの型の変換を行うとできるようになるそうです。

次に検索ドライバにデータを追加します。以下のコマンドで完了。

```
php artisan scout:import 'App\Person'
```
<h1>実際に検索する！</h1>
検索結果を得るためのControllerを作成します。

```
php artisan make:controller PersonController
```

としたのち、コントローラーを以下の用に編集します。

```PersonController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Name;
use App\Person;


class PersonController extends Controller
{
    public function index(Request $request){

        
        $results = Person::search($request->str_1)->get();
        return view('top.index')->with('results',$results);
                                
    }

}

```

(全文検索フォームのinputのnameをstr_1としています)

(ルーティングとviewの書き方は省略します)

ここまでできれば、検索フォームで好きな文字列を入力して検索ができます。ちなみに`$results`をそのままviewで表示させるとjson型で返ってきていることが確認できます！

<h1>最後に</h1>
とにかく実装が楽でした。
他にも色々カスタマイズできるみたいです。実装していく中で気がついた点をまた投稿できたらなと。
今回参考文献はLaravel公式ドキュメントしかないです。

stackshareで調べてみるとAmazon elasticsearch serviceから乗り換えている人も結構いるみたいでAlgoliaの方が高く評価されていた！(と思う)
お金はかかるけどやっぱり有料コンテンツって最高なんやな〜

<h1>追記</h1>
Fakerはデフォルトだと英語で入ってしまうので、日本語のデータが欲しい場合は`config/app.php`に

```config/app.php
'faker_locale'=>'ja_JP'
```
を追記してください！
多分キャッシュが残っているのでターミナルで

```
php artisan config:cache
```
を忘れずに。

<h1>参考にさせていただいた記事・関連記事</h1>
[Instant Search with Laravel Scout & Algolia](https://qiita.com/avosalmon/items/b7b90c734709093fb927)
[Nuxt.js+Algoliaで全文検索可能なタスク管理アプリを実装するハンズオン！](https://qiita.com/mido_app/items/919839aaf33382d9bc89)