意外と簡単!Laravel で全文検索をつくる(Laravel Scout + Algolia)

さてさて、Laravelにはこの間公開したLaravel Passportで自分の登録データを取得するで紹介したような公式パッケージがいくつか存在していて、他にはソーシャルログインを実装するSocialiteが有名なところだと思います。

そして、私がもうひとつ以前から気になっていたのが、「Laravel Scout」です。

Larave Scout は、全文検索を実装するパッケージのことで、サンプルとしては、Laravel本家のウェブサイトで検索してみるとわかりやすいでしょう。

もし全文検索が実装されると、訪問ユーザーは目的のコンテンツを見つけやすくなるので、特に検索機能が重要なウェブサイトの場合は強直な武器になるのではないでしょうか。

ということで、今回はLaravel Scoutを使って全文検索を実装する方法を紹介します。

ぜひ皆さんのお役に立てると嬉しいです😊✨

開発環境:Laravel 5.8

Laravel Scout の仕組み

Laravel Scoutでは、algoliaというウェブサイトを利用して全文検索を実現しています。

つまり、データベースの内容を事前にalgoliaへ登録しておいて、後から検索キーワードを送信することで簡単に全文検索を実現することができるというわけですね。

ちなみにalgoliaには、非商用向けに無料のアカウントを作成できるようになっていて、その場合は以下の制限がつくことになります。(2019.06.15現在)

  • オペレーション(追加や検索などで1オペレーションになる):50,000 回/月
  • データ数:10,000 件

Laravelにパッケージをインストールする

まずはalgoliaから登録してもいいのですが、設定ファイルをパッケージからコピーするので、先に以下のコマンドでLaravel Scoutをインストールしておきましょう。

composer require laravel/scout

続いて、パッケージからファイルをパブリッシュ(コピー)します。

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

これでconfig/scout.phpが作成されました。
続いてクライアントのパッケージです。

composer require algolia/algoliasearch-client-php:^2.2

これでパッケージのインストールは完了です。

algoliaの設定をする

algoliaにアカウントを作成する

では、algoliaのトップページへアクセスして、画面右上にある「FREE TRIAL」ボタンをクリックします。

するとメールアドレスとパスワードの入力フォームが表示されますので、この2つと利用規約のチェックボックスにチェックをオンにして送信します。

すると、入力したメールアドレスに以下のようなメッセージが送信されてきますので、「Confirm my email」ボタンをクリック。

ボタンをクリックすると、あなたについての入力を求められます。
内容は次のとおりです。

  • First name ・・・ 名
  • Last name ・・・ 姓
  • Company ・・・ 会社
  • Phone ・・・ 電話番号(省略可)
  • Wat would describe you the most? ・・・ あなたについて当てはまるものを選んでください。(ぴったりのコンテンツを提供するための質問だそうですので、だいたいでいいかもしれません😂)

入力が完了したら、「Next」ボタンをクリックします。

すると、どの地域のサーバーを使うかを選べるますので、Japanを選択(おそらく自動的に選択されると思います)して「Next」ボタンをクリック。

続いて、どんな使い方をするか聞いてきますが、後で登録することもできますので、今回は「Skip」ボタンをクリックして省略することにします。

これでアカウント登録は完了です。

algoliaのAPIキーをLaravelに登録する

algoliaに登録したらLaravel側からのアクセスに必要なAPIキーを取得しておきましょう。

まずはログインして、画面左側にあるメニューから「API Kyes」をクリックします。

すると、APIキーが表示されます。

それぞれをコピーしてconfig/scout.phpに以下のように登録してください。

'algolia' => [
    'id' => env('ALGOLIA_APP_ID', '(Application IDがここ)'),
    'secret' => env('ALGOLIA_SECRET', '(ADMIN API Keyがここ)'),
],

Search-Only API Keyは使いませんので気をつけてください。

全文検索する部分をつくる

では、本題の全文検索を実装する部分を作っていきましょう。

テストデータをつくる

まずは検索するためのデータがないと始まりませんので、以下のようなSeederを作成してテストデータを用意します。

<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $names = [
            'taro' => '太郎',
            'jiro' => '次郎',
            'saburo' => '三郎',
            'shiro' => '四郎',
            'goro' => '五郎',
            'rokuro' => '六郎',
            'shichiro' => '七郎',
            'hachiro' => '八郎',
            'kuro' => '九郎'
        ];

        foreach ($names as $name_en => $name_jp) {

            \App\User::create([
                'name' => $name_jp,
                'email' => $name_en .'@example.com',
                'password' => bcrypt('xxxxxxxx')
            ]);

        }
    }
}

Seederの作り方は以下のページの「ログイン、パスワードリマインダー機能を構築」をご覧ください。

【Laravel5.6】インストール直後にやること3点

Seederを実行するとこうなりました。

ただし、このままではalgoliaの方にデータが存在していませんので以下のコマンドで一気にデータをアップロードしておきましょう。

php artisan scout:import "App\User"

App\Userの部分は適宜変更してください。

実行すると次のような表示になります。

では、algoliaでどうなっているかを見てみましょう。
メニューの「Indices」をクリックします。

もし、うまくアップロードできていれば次のようになっています。

ちなみに逆にalgoliaのデータ全てを削除する場合は以下のコマンドを実行してください。

php artisan scout:flush "App\User"

モデルを全文検索に対応させる

Laravel Scoutはインストールするだけで有効になるわけではなく、以下のようにSearchableトレイトを追加する必要があります。(つまり、今回はapp/User.phpですが、適宜お好みのモデルで設定してください)

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Scout\Searchable;

class User extends Authenticatable
{
    use Notifiable, Searchable;

※ Searchableを設定すると、データが追加、更新、削除された場合は自動的にalgoliaの方のデータも同期されることになります。

テストしてみる

では、これで基本的な設定は全て完了しましたので、routes/web.phpに以下のようにルーティングを追加してテストしてみましょう。

Route::get('user_search', function(){

    $users = \App\User::search('太郎')->get();

    foreach ($users as $user) {

        echo '<li>'. $user->name .'</li>';

    }

});

これをブラウザで表示すると次のようになります。

これだけみると通常の検索と変わりませんが、例えばメールアドレスをターゲットにして「ro」というキーワードで検索しても「六郎」しか結果は返ってきません。これは、「taro」「jiro」という単語ごとに検索してくれているからです。

そして、algoliaはあいまい検索にも対応していて、「siro」で検索してみると、次のように似た検索結果を自動的に返してくれます。

※ 「shiro」と「jiro」が検索にヒットしています。このあたりがalgoliaの価値ですね。

なお、複数キーワードで検索する場合は空白でつないで使います。

\App\User::search('taro example')->get();

そして、もちろんpaginate()も使うことができますよ!

$users = \App\User::search('太郎')->paginate();
dd($users->toArray());

お疲れ様でした!

おまけ:検索対象にする項目を指定する

例えば、検索する項目をemailnameだけに制限したい場合です。

この場合、先ほどデータを確認したIndicesページの「Configuration」タブをクリックし、さらに「Add as Searchble Attribute」リンクをクリックしてください。

すると以下のように検索項目を選択できますので、好きなものを選びます。

項目を選ぶとこうなります。

最後に忘れずに「Save settings」ボタンをクリックしてください。

おわりに

ということで、今回はLaravelで全文検索をサクッと実装する方法を紹介しました。

今まで自前で全文検索を自前で実装するには、mecabなどで分かち書きするなどめんどうな設定が多くありますが、Laravel Scoutを使えばそういう作業も全てスキップさせることができます。

また、途中でもちらっと書いたあいまい検索ですがこちらの記事によると日本語の検索には特殊なシステムを使って実現しているようですので(やっぱり機械学習とかでしょうか??)、より精度が高い検索を実現することができそうですね。

ぜひ、検索が重要なecサイトなどの開発に導入を検討してみてはいかがでしょうか。

ではでは〜♪

 

この記事が役立ちましたらシェアお願いします😊✨