検索
Meilisearchで確認
Meilisearchのダッシュボードで、検索ワードを指定して検索してみましょう。
非常に高速に検索結果が返ってきます。
Laravelで実装
web.phpに検索結果を返却する処理を追加します。
「ex」という文字列を検索して、Scoutを通じてMeilisearchから検索結果を取得します。
use App\Models\Post;
Route::get('/search', function () {
$posts = Post::search('ex')->get();
return $posts;
});
以下のURLにアクセスします。
http://localhost/search
応答結果を確認します。
もちろん日本語でも検索ができます。
Meilisearchの検索結果と同じ結果のJSONを取得することができました。
データの登録・変更・削除
登録
モデルにSearchableを追加していますので、普通にDBに登録する処理でインデックスに登録できます。
use App\Models\Post;
$post = new Post;
$post->title = "タイトルです";
$post->body = "本文です";
$post->save();
DBに登録と同時に、インデックスにも登録されます。
インデックスを作成する条件を指定できます。
例えば、公開日が設定されているデータのみ、インデックスに登録することができます。
モデルを修正して、shouldBeSearchable
関数を実装します。
以下のコードでは、公開日が設定されている場合にのみ、インデックスに登録できます。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use HasFactory;
use Searchable;
/**
* 公開しているかどうか
*
* @return bool
*/
public function isPublished()
{
return !is_null($this->published_at);
}
/**
* モデルを検索可能にする判定
*
* @return bool
*/
public function shouldBeSearchable()
{
return $this->isPublished();
}
}
変更
更新も通常通りの処理で、インデックスも更新されます。
use App\Models\Post;
$post = Post::find(101);
$post->title = "タイトル更新です";
$post->body = "本文更新です";
$post->save();
インデックスも更新されます。
削除
削除も同様で、以下のようなコードでインデックスから削除されます。
use App\Models\Post;
$post = Post::find(101);
$post->delete();
APIキーの設定
Sailは標準でMeilisearchが使えるようになっていますが、マスターキーやAPIキーが設定されていないため、誰でも操作可能です。
開発で使う分には問題ありませんが、マスターキーを設定してみましょう。
docker-compose.ymlを修正します。MEILI_MASTER_KEY
を追加し、マスターキーを指定します。
‘master_key’という文字列を指定していますが、任意の文字列を指定してください。
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
environment:
MEILI_MASTER_KEY: 'master_key'
Meilisearchのダッシュボードを開いてみましょう。
マスターキーを入力して、データにアクセスできるようになります。
マスターキーを追加すると、自動的に二つのキーが追加になります。
以下のコマンドを実行し、APIキーを確認します。
‘master_key’はマスターキーを指定します。
$ curl \
-X GET 'http://localhost:7700/keys' \
-H 'Authorization: Bearer master_key'
以下のようなJSONデータが取得できました。
“key”という項目がAPIキーになります。
{"results":[
{"name":"Default Search API Key","description":"Use it to search from the frontend","key":"xxxxxxx","uid":"xxxxxxx","actions":["search"],"indexes":["*"],"expiresAt":null,"createdAt":"2022-10-19T13:33:29.943963186Z","updatedAt":"2022-10-19T13:33:29.943963186Z"},
{"name":"Default Admin API Key","description":"Use it for anything that is not a search operation. Caution! Do not expose it on a public frontend","key":"xxxxxxx","uid":"xxxxxxx","actions":["*"],"indexes":["*"],"expiresAt":null,"createdAt":"2022-10-19T13:33:29.934972068Z","updatedAt":"2022-10-19T13:33:29.934972068Z"}
],"offset":0,"limit":20,"total":2}
.envに、Default Admin API Keyのkeyを指定します。
MEILISEARCH_KEY=xxxx
APIキーを追加した場合は、モデルの保存時に正常にインデックスに登録できます。
ただしAPIキーが間違っている場合は、以下のエラーが表示されます。
The Authorization header is missing. It must use the bearer authorization method.
APIキーによるアクセス制限ができますので、詳しくは公式サイトをご覧ください。
データベースエンジンを使う
今回はLaravel Scoutを使いエンジンにMeilisearchを使いましたが、データベースを使用することもできます。
まずは、Meilisearchをエンジンとしている場合、どのようなSQL文を発行しているのか確認してみましょう。
\DB::enableQueryLog();
$posts = Post::search('赤')->get();
\Log::debug(\DB::getQueryLog());
ログファイルを確認しましょう。
IN句にIDを指定して検索していました。
ScoutはMeilisearchの検索結果からIDだけを取得し、Eloquentで取得し直している感じでしょうか。
[2022-10-19 13:48:41] local.DEBUG: array (
0 =>
array (
'query' => 'select * from `posts` where `posts`.`id` in (89, 53, 90, 92, 41, 72, 52, 36, 38, 76, 98, 20, 1, 37, 84, 10, 91, 99, 97, 2)',
'bindings' =>
array (
),
'time' => 2.76,
),
)
次に、エンジンをデータベースに変更してみます。
.envを修正します。
SCOUT_DRIVER=database
モデルを修正し、以下を追加します。
検索対象の項目を指定します。
/**
* モデルに対するインデックス可能なデータの配列を取得
*
* @return array
*/
public function toSearchableArray()
{
return [
'title' => $this->title,
'body' => $this->body,
];
}
先ほど同様、検索を行いログを確認しました。
Like検索で直接データベースから検索していることが分かります。
[2022-10-19 14:04:20] local.DEBUG: array (
0 =>
array (
'query' => 'select * from `posts` where (`posts`.`title` like ? or `posts`.`body` like ?) order by `id` desc',
'bindings' =>
array (
0 => '%赤%',
1 => '%赤%',
),
'time' => 3.02,
),
)
その他
初学者へ
Laravelを初めて触る方へ向け、手順やアドバイスをまとめました。
外部サーバーへ公開
作成したアプリは公開して使ってもらいましょう!
Laravelアプリケーションを外部公開する方法をまとめました。
脆弱性対策
脆弱性を抱えたアプリケーションの場合、攻撃を受ける可能性があり大変危険です。
作成したアプリケーションは、脆弱性対策も意識しましょう。
GitHubと連携
GitHubと連携する方法を解説しました。
プロジェクトの管理はGitHubを活用しましょう。
GitHub Copilot
GitHub Copilotを導入し、AIにコーディングをサポートしてもらうこともできます。
さいごに
今回は、Laravel Scoutを使い、検索エンジンにMeilisearchを使用して実装を行いました。
是非、全文検索を実装する際に参考にしてください。
他にも私のブログで、Laravelについて解説している記事がありますのでご覧ください。
コメント