Laravel Scout を使用して全文検索を有効にする

公開: 2023-05-08

Laravel フレームワークは、Web サービスを構築する開発者にとって頼りになるリソースとなっています。

オープンソース ツールとして、Laravel は、開発者が堅牢で機能的なアプリケーションを構築できるようにする、すぐに使える無数の機能を提供します。

その製品の中には、アプリケーションの検索インデックスを管理するためのライブラリである Laravel Scout があります。 その柔軟性により、開発者は構成を微調整し、インデックスを保存するドライバーを Algolia、Meilisearch、MySQL、または Postgres から選択できます。

ここでは、このツールを詳しく調べて、ドライバーを通じて Laravel アプリケーションに全文検索サポートを追加する方法を説明します。 モックアップ列車の名前を保存するためのデモ Laravel アプリケーションをモデル化し、Laravel Scout を使用してアプリケーションに検索を追加します。

前提条件

これに従うには、次のものが必要です。

  • コンピューターにインストールされている PHP コンパイラー。 このチュートリアルでは PHP バージョン 8.1 を使用します。
  • コンピューターにインストールされている Docker エンジンまたは Docker Desktop
  • 無料で作成できる Algolia クラウド アカウント
アプリをもっと使いやすくしたいですか? 全文検索のサポートを追加してみてください。 Laravel Scout を使用する方法は次のとおりです ️ クリックしてツイート

LaravelプロジェクトにScoutをインストールする方法

Scout を使用するには、まず検索機能を追加する Laravel アプリケーションを作成する必要があります。 Laravel-Scout Bash スクリプトには、Docker コンテナ内で Laravel アプリケーションを生成するコマンドが含まれています。 Docker を使用すると、MySQL データベースなどの追加のサポート ソフトウェアをインストールする必要がなくなります。

Laravel-scout スクリプトは Bash スクリプト言語を使用するため、Linux 環境内で実行する必要があります。 Windows を実行している場合は、Windows Subsystem for Linux (WSL) を必ず構成してください。

WSL を使用している場合は、ターミナルで次のコマンドを実行して、優先する Linux ディストリビューションを設定します。

 wsl -s ubuntu

次に、プロジェクトを配置するコンピュータ上の場所に移動します。 Laravel-Scout スクリプトはここにプロジェクト ディレクトリを生成します。 以下の例では、Laravel-Scout スクリプトはデスクトップディレクトリ内にディレクトリを作成します。

 cd /desktop

以下のコマンドを実行して、Laravel-Scout スクリプトを実行します。 必要な定型コードを使用して Docker 化されたアプリケーションをスキャフォールディングします。

 curl -s https://laravel.build/laravel-scout-app | bash

実行後、 cd laravel-scout-appを使用してディレクトリを変更します。 次に、プロジェクト フォルダー内でsail-upコマンドを実行して、アプリケーションの Docker コンテナーを起動します。

注:多くの Linux ディストリビューションでは、昇格された特権を開始するには、 sudoコマンドとともに以下のコマンドを実行する必要がある場合があります。

 ./vendor/bin/sail up

次のようなエラーが発生する可能性があります。

ポートが割り当てられていることを示すエラー
ポートが割り当てられていることを示すエラー。

これを解決するには、 APP_PORT変数を使用して、 sail upコマンド内でポートを指定します。

 APP_PORT=3001 ./vendor/bin/sail up

次に、以下のコマンドを実行して、PHP サーバー上の Artisan を通じてアプリケーションを実行します。

 php artisan serve
Artisan を使用した Laravel アプリケーションの提供
Artisan を使用した Laravel アプリケーションの提供

Web ブラウザから、http://127.0.0.1:8000 にある実行中のアプリケーションに移動します。 アプリケーションはデフォルトのルートで Laravel のようこそページを表示します。

Laravelアプリケーションのウェルカムページ
Laravelアプリケーションのウェルカムページ

Laravel Scoutをアプリケーションに追加する方法

ターミナルでコマンドを入力して、Composer PHP パッケージマネージャーが Laravel Scout をプロジェクトに追加できるようにします。

 composer require laravel/scout

次に、vendor:publish コマンドを使用して Scout 構成ファイルを公開します。 このコマンドは、 scout.php構成ファイルをアプリケーションのconfigディレクトリに公開します。

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

次に、ボイラープレート.envファイルを変更して、 SCOUT_QUEUEブール値を含めます。

SCOUT_QUEUE値を使用すると、Scout が操作をキューに入れることができるようになり、応答時間が短縮されます。 これがないと、Meilisearch のようなスカウト ドライバーは新しい記録をすぐに反映しません。

 SCOUT_QUEUE=true

また、Docker コンテナ内で MySQL データベースを使用するために、ローカルホストを指すように.envファイル内のDB_HOST変数を変更します。

 DB_HOST=127.0.0.1

モデルをマークしてインデックスを構成する方法

Scout は、デフォルトでは検索可能なデータ モデルを有効にしません。 Laravel\Scout\Searchableトレイトを使用して、モデルを検索可能として明示的にマークする必要があります。

まず、デモのTrainアプリケーションのデータ モデルを作成し、それを検索可能としてマークします。

モデルの作成方法

Trainアプリケーションの場合、利用可能な各列車のプレースホルダー名を保存する必要があります。

以下の Artisan コマンドを実行して移行を生成し、 create_trains_tableという名前を付けます。

 php artisan make:migration create_trains_table
create_trains_table という名前の移行を行う
create_trains_table という名前の移行を行う

移行は、指定された名前と現在のタイムスタンプを組み合わせた名前のファイルに生成されます。

Database/migrations/ディレクトリにある移行ファイルを開きます。

タイトル列を追加するには、17 行目のid()列の後に次のコードを追加します。このコードはタイトル列を追加します。

 $table->string('title');

移行を適用するには、以下のコマンドを実行します。

 php artisan migrate
Artisan 移行の適用
Artisan 移行の適用

データベースの移行を実行した後、 app/Models/ディレクトリにTrain.phpという名前のファイルを作成します。

LaravelScoutSearchable トレイトを追加する方法

以下に示すように、 Laravel\Scout\Searchableトレイトをモデルに追加して、 Trainモデルを検索用にマークします。

 <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Searchable; class Train extends Model { use Searchable; public $fillable = ['title'];

また、 searchableメソッドをオーバーライドして検索インデックスを構成する必要があります。 Scout のデフォルトの動作では、モデル テーブル名と一致するようにモデルが永続化されます。

したがって、次のコードをTrain.phpファイルの前のブロックのコードの下に追加します。

 /** * Retrieve the index name for the model. * * @return string */ public function searchableAs() { return 'trains_index'; } }

Scout で Algolia を使用する方法

Laravel Scout を使用した最初の全文検索では、Algolia ドライバーを使用します。 Algolia は、大量のデータを検索するために使用されるサービスとしてのソフトウェア (SaaS) プラットフォームです。 開発者が検索インデックスを管理するための Web ダッシュボードと、好みのプログラミング言語でソフトウェア開発キット (SDK) を介してアクセスできる堅牢な API を提供します。

Laravel アプリケーション内では、PHP 用の Algolia クライアント パッケージを使用します。

アルゴリアの設定方法

まず、アプリケーション用の Algolia PHP 検索クライアント パッケージをインストールする必要があります。

以下のコマンドを実行します。

 composer require algolia/algoliasearch-client-php

次に、Algolia からのアプリケーション ID とシークレット API キーの資格情報を.envファイルに設定する必要があります。

Web ブラウザを使用して Algolia ダッシュボードに移動し、アプリケーション ID とシークレット API キーの認証情報を取得します。

左側のサイドバーの下部にある「設定」をクリックして、 「設定」ページに移動します。

次に、[設定] ページの[チームとアクセス]セクション内の[API キー]をクリックして、Algolia アカウントのキーを表示します。

Algolia Cloud の API キー ページへの移動
Algolia Cloud の API キー ページ

[API キー] ページで、アプリケーション ID管理 API キーの値をメモします。 これらの資格情報を使用して、Laravel アプリケーションと Algolia の間の接続を認証します。

Algolia API キー ページからのアプリケーション ID と管理 API キーの表示
アプリケーション ID と管理 API キー

コード エディターを使用して以下のコードを .env ファイルに追加し、プレースホルダーを対応する Algolia API シークレットに置き換えます。

 ALGOLIA_APP_ID=APPLICATION_ID ALGOLIA_SECRET=ADMIN_API_KEY

また、 SCOUT_DRIVER変数を以下のコードに置き換えて、値をmeilisearchからalgoliaに変更します。 この値を変更すると、Scout に Algolia ドライバーを使用するように指示されます。

 SCOUT_DRIVER=algolia

アプリケーション コントローラーの作成方法

app/Http/Controllers/ディレクトリ内に、アプリケーションのコントローラーを保存するTrainSearchController.phpファイルを作成します。 コントローラーはデータをリストし、 Trainモデルに追加します。

次のコード ブロックをTrainSearchController.phpファイルに追加して、コントローラーを構築します。

 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Models\Train; class TrainSearchController extends Controller { /** * Get the index name for the model. * * @return string */ public function index(Request $request) { if($request->has('titlesearch')){ $trains = Train::search($request->titlesearch) ->paginate(6); }else{ $trains = Train::paginate(6); } return view('Train-search',compact('trains')); } /** * Get the index name for the model. * * @return string */ public function create(Request $request) { $this->validate($request,['title'=>'required']); $trains = Train::create($request->all()); return back(); } }

アプリケーションルートの作成方法

このステップでは、新しい列車をリストしてデータベースに追加するためのルートを作成します。

Routes/web.phpファイルを開き、既存のコードを以下のブロックに置き換えます。

 <?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\TrainSearchController; Route::get('/', function () { return view('welcome'); }); Route::get('trains-lists', [TrainSearchController::class, 'index']) -> name ('trains-lists'); Route::post('create-item', [TrainSearchController::class, 'create']) -> name ('create-item');

上記のコードは、アプリケーション内で 2 つのルートを定義します。 /trains-listsルートのGETリクエストは、保存されているすべての列車データをリストします。 /create-itemルートのPOSTリクエストは、新しい列車データを作成します。

アプリケーションビューの作成方法

resource/views/ディレクトリ内にファイルを作成し、 Train-search.blade.phpという名前を付けます。 このファイルには、検索機能のユーザー インターフェイスが表示されます。

以下のコード ブロックの内容をTrain-search.blade.phpファイルに追加して、検索機能用の単一ページを作成します。

 <!DOCTYPE html> <html> <head> <title>Laravel - Laravel Scout Algolia Search Example</title> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container"> <h2 class="text-bold">Laravel Full-Text Search Using Scout </h2><br/> <form method="POST" action="{{ route('create-item') }}" autocomplete="off"> @if(count($errors)) <div class="alert alert-danger"> <strong>Whoops!</strong> There is an error with your input. <br/> <ul> @foreach($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <input type="hidden" name="_token" value="{{ csrf_token() }}"> <div class="row"> <div class="col-md-6"> <div class="form-group {{ $errors->has('title') ? 'has-error' : '' }}"> <input type="text" name="title" class="form-control" placeholder="Enter Title" value="{{ old('title') }}"> <span class="text-danger">{{ $errors->first('title') }}</span> </div> </div> <div class="col-md-6"> <div class="form-group"> <button class="btn btn-primary">Create New Train</button> </div> </div> </div> </form> <div class="panel panel-primary"> <div class="panel-heading">Train Management</div> <div class="panel-body"> <form method="GET" action="{{ route('trains-lists') }}"> <div class="row"> <div class="col-md-6"> <div class="form-group"> <input type="text" name="titlesearch" class="form-control" placeholder="Enter Title For Search" value="{{ old('titlesearch') }}"> </div> </div> <div class="col-md-6"> <div class="form-group"> <button class="btn btn-primary">Search</button> </div> </div> </div> </form> <table class="table"> <thead> <th>Id</th> <th>Train Title</th> <th>Creation Date</th> <th>Updated Date</th> </thead> <tbody> @if($trains->count()) @foreach($trains as $key => $item) <tr> <td>{{ ++$key }}</td> <td>{{ $item->title }}</td> <td>{{ $item->created_at }}</td> <td>{{ $item->updated_at }}</td> </tr> @endforeach @else <tr> <td colspan="4">No train data available</td> </tr> @endif </tbody> </table> {{ $trains->links() }} </div> </div> </div> </body> </html>

上記の HTML コードには、データベースに保存する前に列車のタイトルを入力するための入力フィールドとボタンを備えたフォーム要素が含まれています。 このコードには、データベース内の列車エントリのidtitlecreated_at 、およびupdated_at の詳細を表示する HTML テーブルもあります。

アルゴリア検索の使用方法

このページを表示するには、Web ブラウザから http://127.0.0.1:8000/trains-lists に移動します。

列車リスト ページ内に表示される列車モデル データの表示
モデルデータのトレーニング

データベースは現在空であるため、入力フィールドにデモ列車のタイトルを入力し、 [新しい列車の作成]をクリックして保存する必要があります。

新しい列車エントリの挿入
新しい列車エントリの挿入

検索機能を使用するには、保存されている列車タイトルのキーワードを[検索するタイトルを入力してください] 入力フィールドに入力し、 [検索]をクリックします。

下の画像に示すように、タイトルにキーワードを含む検索エントリのみが表示されます。

検索機能を使用して列車の入口を見つける
検索機能を使用して列車の入口を見つける

Laravel Scout を使用した Meil​​isearch

Meilisearch は、速度、パフォーマンス、開発者エクスペリエンスの向上に重点を置いたオープンソースの検索エンジンです。 同じアルゴリズム、データ構造、研究を使用し、いくつかの機能を Algolia と共有していますが、使用しているプログラミング言語が異なります。

開発者は、オンプレミスまたはクラウド インフラストラクチャ内で Meil​​isearch インスタンスを作成し、自己ホストできます。 Meilisearch は、インフラストラクチャを管理せずに製品を使用したい開発者向けに、Algolia と同様のベータ クラウド サービスも提供しています。

このチュートリアルでは、Docker コンテナ内で Meil​​isearch のローカル インスタンスがすでに実行されています。 次に、Meilisearch インスタンスを使用するように Laravel Scout 機能を拡張します。

Meilisearch を Laravel アプリケーションに追加するには、プロジェクト ターミナルで以下のコマンドを実行します。

 composer require meilisearch/meilisearch-php

次に、 .envファイル内の Meil​​isearch 変数を変更して構成する必要があります。

.envファイル内のSCOUT_DRIVERMEILISEARCH_HOST 、およびMEILISEARCH_KEY変数を以下のものに置き換えます。

 SCOUT_DRIVER=meilisearch MEILISEARCH_HOST=http://127.0.0.1:7700 MEILISEARCH_KEY=LockKey

SCOUT_DRIVERキーは Scout が使用するドライバーを指定し、 MEILISEARCH_HOST Meil​​isearch インスタンスが実行されているドメインを表します。 開発時には必須ではありませんが、運用環境ではMEILISEARCH_KEYを追加することをお勧めします。

注: Meil​​isearch を優先ドライバーとして使用する場合は、Algolia ID と Secret をコメント化します。

.env構成が完了したら、以下の Artisan コマンドを使用して既存のレコードにインデックスを付ける必要があります。

 php artisan scout:import "App\Models\Train"

Laravel Scoutとデータベースエンジン

Scout のデータベース エンジンは、小規模なデータベースを使用するアプリケーションや、それほど負荷がかからないワークロードを管理するアプリケーションに最適です。 現在、データベース エンジンは PostgreSQL と MySQL をサポートしています。

このエンジンは、「where-like」句と既存のデータベースに対する全文インデックスを使用して、最も関連性の高い検索結果を見つけることができます。 データベース エンジンを使用する場合、レコードにインデックスを付ける必要はありません。

データベース エンジンを使用するには、 SCOUT_DRIVER .env変数をデータベースに設定する必要があります。

Laravel アプリケーション内で.envファイルを開き、 SCOUT_DRIVER変数の値を変更します。

 SCOUT_DRIVER = database

ドライバーをデータベースに変更すると、Scout は全文検索にデータベース エンジンの使用に切り替えます。

Laravel Scoutを使用したコレクションエンジン

データベース エンジンに加えて、Scout はコレクション エンジンも提供します。 このエンジンは、「where」句とコレクション フィルタリングを使用して、最も関連性の高い検索結果を抽出します。

データベース エンジンとは異なり、コレクション エンジンは、Laravel もサポートするすべてのリレーショナル データベースをサポートします。

コレクション エンジンを使用するには、 SCOUT_DRIVER環境変数をcollectionに設定するか、Scout 構成ファイルでコレクション ドライバーを手動で指定します。

 SCOUT_DRIVER = collection

Elasticsearch を使用したエクスプローラー

Elasticsearch クエリの強力な機能を備えた Explorer は、Laravel Scout 用の最新の Elasticsearch ドライバーです。 互換性のある Scout ドライバーを提供し、大量のデータをリアルタイムで保存、検索、分析するなどの利点を提供します。 Laravel を使用した Elasticsearch では、ミリ秒単位で結果が得られます。

Laravel アプリケーションで Elasticsearch Explorer ドライバーを使用するには、Laravel-Scout スクリプトが生成したボイラープレートdocker-compose.ymlファイルを構成する必要があります。 Elasticsearch の追加構成を追加し、コンテナーを再起動します。

docker-compose.ymlファイルを開き、その内容を次のものに置き換えます。

 # For more information: https://laravel.com/docs/sail version: '3' services: laravel.test: build: context: ./vendor/laravel/sail/runtimes/8.1 dockerfile: Dockerfile args: WWWGROUP: '${WWWGROUP}' image: sail-8.1/app extra_hosts: - 'host.docker.internal:host-gateway' ports: - '${APP_PORT:-80}:80' - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' environment: WWWUSER: '${WWWUSER}' LARAVEL_SAIL: 1 XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' volumes: - '.:/var/www/html' networks: - sail depends_on: - mysql - redis - meilisearch - mailhog - selenium - pgsql - elasticsearch mysql: image: 'mysql/mysql-server:8.0' ports: - '${FORWARD_DB_PORT:-3306}:3306' environment: MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' MYSQL_ROOT_HOST: "%" MYSQL_DATABASE: '${DB_DATABASE}' MYSQL_USER: '${DB_USERNAME}' MYSQL_PASSWORD: '${DB_PASSWORD}' MYSQL_ALLOW_EMPTY_PASSWORD: 1 volumes: - 'sail-mysql:/var/lib/mysql' - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' networks: - sail healthcheck: test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"] retries: 3 timeout: 5s elasticsearch: image: 'elasticsearch:7.13.4' environment: - discovery.type=single-node ports: - '9200:9200' - '9300:9300' volumes: - 'sailelasticsearch:/usr/share/elasticsearch/data' networks: - sail kibana: image: 'kibana:7.13.4' environment: - elasticsearch.hosts=http://elasticsearch:9200 ports: - '5601:5601' networks: - sail depends_on: - elasticsearch redis: image: 'redis:alpine' ports: - '${FORWARD_REDIS_PORT:-6379}:6379' volumes: - 'sail-redis:/data' networks: - sail healthcheck: test: ["CMD", "redis-cli", "ping"] retries: 3 timeout: 5s pgsql: image: 'postgres:13' ports: - '${FORWARD_DB_PORT:-5432}:5432' environment: PGPASSWORD: '${DB_PASSWORD:-secret}' POSTGRES_DB: '${DB_DATABASE}' POSTGRES_USER: '${DB_USERNAME}' POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}' volumes: - 'sailpgsql:/var/lib/postgresql/data' networks: - sail healthcheck: test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}"] retries: 3 timeout: 5s meilisearch: image: 'getmeili/meilisearch:latest' ports: - '${FORWARD_MEILISEARCH_PORT:-7700}:7700' volumes: - 'sail-meilisearch:/meili_data' networks: - sail healthcheck: test: ["CMD", "wget", "--no-verbose", "--spider", "http://localhost:7700/health"] retries: 3 timeout: 5s mailhog: image: 'mailhog/mailhog:latest' ports: - '${FORWARD_MAILHOG_PORT:-1025}:1025' - '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025' networks: - sail selenium: image: 'selenium/standalone-chrome' extra_hosts: - 'host.docker.internal:host-gateway' volumes: - '/dev/shm:/dev/shm' networks: - sail networks: sail: driver: bridge volumes: sail-mysql: driver: local sail-redis: driver: local sail-meilisearch: driver: local sailpgsql: driver: local sailelasticsearch: driver: local

次に、以下のコマンドを実行して、 docker-compose.ymlファイルに追加した新しい Elasticsearch イメージをプルします。

 docker-compose up

次に、以下の Composer コマンドを実行して、エクスプローラーをプロジェクトにインストールします。

 composer require jeroen-g/explorer

Explorer ドライバー用の構成ファイルを作成する必要もあります。

以下の Artisan コマンドを実行して、構成を保存するためのexplorer.configファイルを生成します。

 php artisan vendor:publish --tag=explorer.config

上記で生成された構成ファイルは、 /configディレクトリで使用できます。

config/explorer.phpファイルでは、 indexesキーを使用してモデルを参照できます。

 'indexes' => [ \App\Models\Train::class ],

.envファイル内のSCOUT_DRIVER変数の値をelasticに変更して、Scout が Explorer ドライバーを使用するように構成します。

 SCOUT_DRIVER = elastic

この時点で、Explorer インターフェイスを実装し、 mappableAs()メソッドをオーバーライドすることで、 Trainモデル内で Explorer を使用します。

App > Modelsディレクトリ内のTrain.phpファイルを開き、既存のコードを以下のコードに置き換えます。

 <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use JeroenG\Explorer\Application\Explored; use Laravel\Scout\Searchable; class Train extends Model implements Explored { use HasFactory; use Searchable; protected $fillable = ['title']; public function mappableAs(): array { return [ 'id'=>$this->Id, 'title' => $this->title, ]; } }

上で追加したコードを使用すると、エクスプローラーを使用してTrainモデル内のテキストを検索できるようになります。

Laravel + Scout = 高速、堅牢、クリーンな全文検索の統合。 デモアプリを構築し、このガイドに従って試してみてください ️ クリックしてツイートしてください

まとめ

PHP 開発者にとって、Laravel と Scout などのアドオンを使用すると、高速で堅牢な全文検索機能を簡単に統合できます。 データベース エンジン、コレクション エンジン、Meilisearch および Elasticsearch の機能を使用すると、アプリのデータベースと対話し、高度な検索メカニズムをわずか数ミリ秒で実装できます。

データベースのシームレスな管理と更新は、コードがクリーンで効率的な状態を保ちながら、ユーザーが最適なエクスペリエンスを享受できることを意味します。

Kinstaは、アプリケーションおよびデータベースホスティングソリューションを備えており、最新のLaravel開発ニーズをすべて満たすワンストップショップです。 最初の 20 ドルは私たちの負担です。