Laravel ScoutはLaravelのドキュメントサイトでも利用されているような全文検索を行うためのパッケージです。Laravel Scoutでは検索機能にalgoliaを利用することで高速に検索結果が表示されるだけでなくLaravel側で更新したデータをalogolia内で管理するデータと同期することが可能です。

algoliaに検索を行いたいデータをimportすることでローカルのデータを利用して検索を行うのではなくalgoliaにアクセスを行いalgoliaに保存されているデータを利用して検索結果を取得しています。検索だけではなくデータの追加や更新もLaravel Scoutを通してローカルデータとalgoliaを同期することができるため一度設定を行ってしまえばモデルを介してローカルのデータベースにアクセスしているように処理を行うことができるためalogliaを意識することがなくなります。

本文書ではalgoliaのアカウントの作成から検索の実行、ローカルデータベースとalgoliaのデータ同期について確認を行い、Reactでの検索UIの実装方法も説明しています。

Laravel Scoutはalgolia専用のパッケージではないのでalgoliaの他にオープンソースのMeiliSearchを利用することができます。

Algoliaについて

検索機能についてこれまで気にしたことがなければalgoliaという名前を聞いたことがない人もいるのではないでしょうか。algoliaはSearch as a serviceとして検索機能をクラウドサービスとして提供しておりLaravelのドキュメントの検索に利用されているだけではなくTailwindcss, Vue.js, Nuxt.js, React, Next.jsなど本ブログで度々紹介するオープソースのプロダクトだけではなく個人のサイトから商用サイトまで幅広く利用されています。実際にLaravelのドキュメント」サイトで検索を実施してみると検索結果が高速で表示されることを体感することができます。alogoliaは検索機能だけではなく検索情報を分析する機能を合わせ持っているためサイトを訪れるユーザがどのような情報を求めているかがわかります。

algoliaが利用されているかどうかは検索結果の右下に表示される”search by algolia”で判断することもできます。

algoliaを検索に利用しているReact
algoliaを検索に利用しているReact

algoliaの使い方の流れをブログを例に説明します。サーバに保存されたブログのタイトルやコンテンツのデータをalgoliaにインポートします。ブログに検索機能を実装し検索を実施するとAPI経由でalgoliaに検索文字列が渡されます。渡した文字列を使ってalgolia内で処理が行われすぐに検索結果を戻すので戻した結果をサーバが受け取り表示させます。流れは非常にシンプルで仕組み自体は難しいものではありません。後ほど説明をしますがLaravel Scoutを利用している場合はモデルを経由して検索を行うことができます。

laravelとalgoliaの関係
laravelとalgoliaの関係

検索機能をブラウザ側のJavaScriptで実装できるようにReact, Vue, Svelteなどに対応したSearch UIが提供されています。その場合はLaravelを介する必要はないのでAlogiliaサーバと直接やりとりを行います。Laravelはデータの追加、更新、削除に関してAlogoliaと連携を行います。本文書ではReactを利用した場合のSearch UIの設定方法について後半で解説しています。

JavaScriptを利用した場合
JavaScriptを利用した場合

Laravel環境の構築

Laravel Scoutパッケージをインストールする前にLaravelの環境を構築します。Laravel構築の手順については本記事では簡易的に行わせてもらいます。

laravel newコマンドで新規のLaravelプロジェクトを作成します。


 % laravel new laravel_scout

データベースは簡易的に作成できるSQLiteを利用します。


 % touch database/database.sqlite

.envファイルを開いてDATABASE_CONNECTIONをsqliteに変更します。DB_CONNECTION以外の環境変数のDB_*は削除してください。


DB_CONNECTION=sqlite

php migrateコマンドを実行してテーブルが作成できることを確認します。


 % php artisan migrate           
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (3.05ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (2.77ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (1.91ms)

Laravel Scoutを利用して検索を行うために利用するのはusersテーブルです。usersテーブルにダミーデータを登録するためにLaravel Seeding機能を利用します。

日本語のダミーデータが作成できるようにconfig/app.phpファイルのfaker_localeの値をja_JPに変更します。


'faker_locale' => 'ja_JP',

次にdatabase¥seeders¥DatabaseSeeder.phpファイルを開いて100名分のユーザデータを登録できるように変更を行います。


    public function run()
    {
        \App\Models\User::factory(100)->create();
    }

php artisan db:seedコマンドを実行してダミーデータをusersテーブルに追加します。


 % php artisan db:seed
Database seeding completed successfully.

本文書ではデータベースの管理ソフトのTablePlusを利用して作成したSQLiteデータベースにアクセスします。100件分のダミーデータを確認することができます。

TablePlusでユーザデータの確認
TablePlusでユーザデータの確認

Laravel/Scoutパッケージのインストール

Laravelのインストールと環境の構築が完了したら、Laravel/Scoutのパッケージのインストールを行います。


 % composer require laravel/scout

インストール完了後、下記のコマンドでScoutのConfigファイルの作成を行います。configフォルダの中にscout.phpファイルが作成されます。


 % php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
Copied File [/vendor/laravel/scout/config/scout.php] To [/config/scout.php]
Publishing complete.

検索を行いたいモデルにLaravel¥Scout¥Seachableトレイトを設定します。app¥Models¥User.phpファイルを開いて設定を行ってください。


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

class User extends Authenticatable
{
    use HasFactory, Notifiable, Searchable;

Algoliaでのアカウント作成

Algoliaでアカウントを作成するためにalgolia.comにアクセスします。トライアル期間が14日間と表示されていますがフリープランも準備されています。アカウントの作成後、アクセスするためのAPIキーを取得します。

Algoliaトップページ
Algoliaトップページ

アカウント作成画面が表示されるのでメールアドレスを入力するかGmail, GitHubのアカウントを利用してください。

アカウントを作成するためにクレジットカードの入力は必要ではありません。

メールアドレス入力画面
メールアドレス入力画面

名前の入力画面が表示されるので、必須項目を入力してください。電話番号は必須ではありません。

個人情報の入力
個人情報の入力

最後の入力項目で会社の名前や規模、役割を選択してください。

会社、規模、役割の入力
会社、規模、役割の入力

メールが送信されるのでメールがalgoliaから届いているかメールボックスを確認してください。

メールアドレスの確認
メールアドレスの確認

Algoliaから送信されたメールを確認して” Confirm my email”ボタンをクリックしてください。

メールの内容
メールの内容

データセンターの場所を選択する画面が表示されます。日本からのレスポンスタイムは77MSであることがわかります。Japanを選択して”Continue Configuration”ボタンをクリックしてください。

データセンターの選択
データセンターの選択

アカウントの作成が完了するとalgoliaのダッシュボードが表示されます。

Algoliaのダッシュボード
Algoliaのダッシュボード

以上でalogoliaのアカウントの作成は完了です。

フリープランへの変更

ダッシュボードの上部にトライアル期間の残り日数が表示されているのでフリープランへ変更するためには”Click here to upgrade your plan”をクリックします。

フリートライアルの期間
フリートライアルの期間

クリックするとプランの選択画面が表示されます。Freeを選択してください。

プランの表示
プランの表示

選択後スクロールをして”Review and Confirm”ボタンをクリックしてください。

フリープランの確認
フリープランの確認

terms of serviceやPrivacy Policyを確認しチェックして問題がなければUpdate Planボタンをクリックしてください。

フリープランへの変更
フリープランへの変更
フリープランの場合は”The Free Plan requires you to display the Algolia logo next to the search results.”と管理画面上に表示されます。検索結果にAlogoliaのログを表示させる必要があります。

Laravel Scoutの設定

先ほど作成したscout.phpファイルを開いてAlgoliaのAPIキーの設定を行います。


'algolia' => [
    'id' => env('ALGOLIA_APP_ID', ''),
    'secret' => env('ALGOLIA_SECRET', ''),
],

idとsecretを設定しますがALGOLIA_APP_IDとALGOLIA_SECRETは.envファイルから設定を行います。

.envファイルを開いてALGOLIA_APP_IDとALGOLIA_SECRETの環境変数を追加してAlgoliaから取得できるApplication IDとAdmin API KEYを設定します。


ALGOLIA_APP_ID=XXXXXX
ALGOLIA_SECRET=XXXXXXXXXXXXXXXXXXXXXXX

左のメニューのAPI KeysをクリックしてApplication IDとAdmin Keyを取得してください。Admin Keyを利用することで検索だけではなくデータの登録を行うことができます。

IDとキーをAlgoliaから取得
IDとキーをAlgoliaから取得
Search-Only KeyとAdmin API KeyがありますがLaravel Scoutでは検索だけではなくデータの追加・更新・削除も行うのでAdmin API Keyを利用します。

idとsecretの設定ができたらalgoliasearch-client-phpのインストールを行います。


 % composer require algolia/algoliasearch-client-php
algoliasearch-client-phpパッケージ単独でもalgoliaにアクセスを行い各種設定を行うことが可能です。algoliaのドキュメントにも使用方法は記載されているので理解を深めたい人はぜひローカルにパッケージをインストールして動作確認してみてください。

ここまでの設定が完了するとusersテーブルの内容をalogoliaにインポートすることができます。

インポートはphp artisan scout:importコマンドを利用します。インポートの完了メッセージが表示されているのでalgoliaのダッシュボードを確認します。


 % php artisan scout:import "App\Models\User"
Imported [App\Models\User] models up to ID: 100
All [App\Models\User] records have been imported.

ダッシュボードのOverviewを確認するとレコードが100件登録されていることが確認できます。

100件のデータ登録を確認
100件のデータ登録を確認

データをimportすることでalgoliaを利用するために必要となるタスクの中でindexの作成とデータのimportが完了します。最後に検索する属性の設定する必要があります。

algoliaではindexの名前はlaravelのテーブル名に対応するのでデフォルトの設定ではimportしたusersテーブルと同じ名前がindexの名前usersになります。通常のindexは索引という意味でテーブルの列のイメージが強いので最初はalgoliaのindexの意味がわかりにくいかもしれません。
検索する属性を決める
検索する属性を決める

indexの作成とデータのimportが完了したので最後にusersテーブル内のどの列の情報を検索対象とするかをSearchable attributesで選択します。nameとemailを選択します。設定完了後、検索を実施するとnameとemailにある値のみが検索対象となります。

nameとEmailを選択
nameとEmailを選択

Laravel Scoutの動作確認

検索を行う

Userモデルを使って検索を行ってみましょう。まずはalogoliaからデータが取得できるかweb.phpにコードを記述して確認します。

UserモデルではSearchableトレイトを利用しているのでsearchメソッドを使うことができます。searchメソッドの引数に検索したい文字を入力することで検索結果が戻されます。


Route::get('/users',function(){
    $users = \App\Models\User::search('山')->get();
    dd($users);
});

php artisan serveコマンドで開発サーバを起動しブラウザから/usersにアクセスを行ってください。

実行すると文字列の”山”を含むデータが18件取得することできました。Userモデルを介して検索を行うため検索結果が多い場合はpaginateでpaginationを利用することができます。

Algoliaを利用するためにインストールしたalgoliasearch-client-phpパッケージのみを利用しても下記のように検索を行うことができます。Searchableトレイトの中でも同様の処理が行われています。


Route::get('/users',function(){
    // $users = \App\Models\User::search('山')->get();
    $client = Algolia\AlgoliaSearch\SearchClient::create(
        env('ALGOLIA_APP_ID'),
        env('ALGOLIA_SECRET')
    );

    $index = $client->initIndex('users');
    $results = $index->search('山');
    dd($results);
});

戻り値は配列ですがhitsに18件のデータが含まれていることが確認できます。searchableトレイトを利用した時と結果は同じです。

モデルを介さず直接アクセス
モデルを介さず直接アクセス

検索機能の実装

Bladeファイルを作成してalgoriaを利用して検索機能を実装してみましょう。

php artisan make:controllerコマンドでコントローラーの作成を行います。


$ php artisan make:controller UsersController
Controller created successfully.

作成したUsersController.phpファイルにindexメソッドを追加し、Userモデルを利用してすべてのデータを取得します。表示するBladeファイルにはusers.indexを指定します。


namespace App\Http\Controllers;

use App\Models\User;

class UsersController extends Controller
{
    public function index(){

        $users = User::all();

        return view('users.index',['users'=>$users]);

    }
}

resources¥viewsフォルダの下にusersフォルダを作成してindex.blade.phpファイルを作成してください。


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <h1>ユーザ一覧</h1>
  <table border="1">
    <thead>
      <tr>
        <td>id</td>
        <td>name</td>
        <td>email</td>
      </tr>
    </thead>
    <tbody>
      @foreach($users as $user)
      <tr>
        <td>{{ $user->id}}</td>
        <td>{{ $user->name}}</td>
        <td>{{ $user->email}}</td>
      </tr>
      @endforeach
    </tbody>
  </table>
</body>
</html>

ルーティングweb.phpファイルのルーティングで作成したコントローラーのindexメソッドを指定します。


use App\Http\Controllers\UsersController;
//略

Route::get('/users', [UsersController::class, 'index']);

ブラウザで/usersにアクセスを行うユーザ一覧が表示されることを確認します。

ユーザ一覧表示
ユーザ一覧表示

検索が行えるようにinput要素を追加します。getメソッドを使って入力した文字列を/usersに送信しています。


<body>
  <h1>ユーザ一覧</h1>
  <div style="margin:1em 0;">
    <form method="get" action="/users">
    <label for="search">検索</label>
    <input name="search" value=""/>
    <button type="submit">検索</button>
    </form>
  </div>
  <table border="1">

コントローラー側で文字列を取得してsearchメソッドを利用して検索を行いその結果をusers.indexに渡します。


public function index(){

    if(request()->search){
        $users = User::search(request()->search)->get();
    }else{
        $users = User::all();
    }

    return view('users.index',['users'=>$users]);

}

検索用の入力フォームに文字列を入れて検索を入れると入力した文字列を含む文字のみ表示されます。

検索結果後の一覧
検索結果後の一覧

通常の検索機能との違いはsearchメソッドを利用することだけです。このように簡単に検索機能を実装することができます。

データの追加

通常はコントローラーを作成してデータの作成を行いますが、簡易的に行えるtinkerを利用してユーザデータを追加してみましょう。tinkerはLaravelのインストールフォルダでphp artisan tinkerで起動します。


 % php artisan tinker
Psy Shell v0.10.6 (PHP 7.4.10 — cli) by Justin Hileman
>>> $user = new App\Models\User;
=> App\Models\User {#3366}
>>> $user->name = "明智光秀";
=> "明智光秀"
>>> $user->email = "kiringakuru@test.com";
=> "kiringakuru@test.com"
>>> $user->password = bcrypt('password');
=> "$2y$10$ImaIyjf7sGrJNvLLblRSIuCblqcnSvmIOaVjs8iQM4n6HjegkBQs."
>>> $user->save();

ユーザを登録後にalogoliaのダッシュボードでレコード数を確認します。1件追加したので101件になっていることが確認できます。またダッシュボード上で追加したユーザの名前を検索することができます。

alogoliaに自動で登録
alogoliaに自動で登録

データの更新

先ほど追加したデータの名前を更新してalgoliaに更新が反映されるか確認を行います。


>>> $user->name = '明智十兵衛';
=> "明智十兵衛"
>>> $user->update();

ダッシュボードで検索すると更新した名前になっていることが確認できます。

更新結果が自動で反映
更新結果が自動で反映

データの削除

最後にデータの削除も確認しておきます。


>>> $user = App\Models\User::find(102);
=> App\Models\User {#4359
     id: "102",
     name: "明智光秀",
     email: "kiringakuru@test.com",
     email_verified_at: null,
     created_at: "2021-02-18 09:57:13",
     updated_at: "2021-02-18 09:57:13",
   }
>>> $user->delete();
=> true

一度削除をすると以下のエラーメッセージでalgoliaへの反映が失敗しましたが再度同じ流れで実行すると問題なく削除も反映されました。

GuzzleHttp\Exception\ConnectException with message ‘cURL error 28: Operation timed out after 2001 milliseconds with 0 out of 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://XXXXXX.algolia.net/1/indexes/users/batch’

このようにLaravel上で行ったUserモデルへの処理がすべてalgoliaに自動で反映されていることがわかりました。

algolia上のレコードをすべて削除

Laravelからalgolia上のレードを一括で削除したい場合は下記のコマンドで可能です。


% php artisan scout:flush "App\Models\User"

algoliaのダッシュボードからもデータの一括削除、個別削除は可能です。

Indexを削除

alogolia上のIndexのUsersを削除したい場合はダッシュボードから行うことができます。

IndicesのページにあるManage indexのプルダウンメニューからDeleteを選択します。

Indexの削除処理
Indexの削除処理

削除の確認画面が表示されるので削除したい場合はDELETEを入力して”Delete”ボタンをクリックしてください。

DELETEを入力
DELETEを入力
レコードが存在していても削除することができます。

algolia上のindexの名前を変更する

デフォルトではusersテーブルをalgoliaにimportするとindex名はusersという名前になります。index名を指定するためにUser.phpファイルのsearchableAsメソッドに変更したい名前を入力します。ここではuser_indexという名前にしています。任意の名前をつけてみてください。


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

変更後に一括でimportを行うとindex名がuser_indexになっていることが確認できます。


 % php artisan scout:import "App\Models\User"
Imported [App\Models\User] models up to ID: 100
All [App\Models\User] records have been imported.

index名はダッシュボードで確認することができます。

index名の変更の確認
index名の変更の確認

algoliaでindexを作成後にsearchableAsメソッドで設定した名前を変更するとalgoriaからデータは取得できなくなります。searchableAsメソッドで指定した値をalgoriaにアクセスする際に利用していためです。

indexの名前が一致しない場合のエラー
indexの名前が一致しない場合のエラー

ダッシュボード上ではindex名の変更も可能のようです(未実施)。

IndexのレコードのObject IDを変更

デフォルトではレコードのObjectIDにはテーブルのid列が設定されます。これを変更したい場合はUser.phpファイルに以下を追加することでObjectIDがidからemailに変更になります。


public function getScoutKey()
{
    return $this->email;
}
ObjectIDをemailに変更
ObjectIDをemailに変更
LaravelのScoutでObjectIDを元にデータを取得するメソッドを見つけることができませんでしたがalogliaのライブラリのメソッドにはObjectIDを利用するgetObjectメソッドがあります。

importするテーブルの列を制限する

デフォルトではimportを行うとすべてのデータがalgolia側に保存されます。検索対象にならない列をimportさせないこともできます。

User.phpファイルののtoSearchableArrayメソッドの中でunsetメソッドを利用してimportしない列の情報を削除します。


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

    unset($array['created_at']);
    unset($array['updated_at']);
    unset($array['email_verified_at']);

    return $array;
}

時刻に関する列をimportの対象外としたのでalgolia上のusersのデータを一括でimportするとusersデータは下記のように表示されます。

importする列を制限した場合
importする列を制限した場合

ここまででLaravel Scoutとalogoliaの基本的な使用方法を理解することができました。

ReactでAlogoliaを利用する

Laravel8では認証機能のBreezeパッケージをインストールすることでInertia + React環境を構築することができます。Alogloliaが提供するUIライブラリを利用する場合はInertiaを含めLaravelを経由して検索を行われないためLaravelに限らずここで説明する内容はどのReact環境でも設定方法は同じで検索機能を持ったコンポーネントを利用するだけです。

本文書ではLaravelを利用しているのでBreezeをインストールしてReactを利用できる環境を構築します。Laravelとは別にReact環境を構築することでも動作確認は可能です。

Laravel/Breezeパッケージのインストール

composerコマンドを利用してLaravel/Breezeパッケージをインストールします。


$ composer require laravel/breeze --dev

breezeのインストールを行いますがオプションにreactをつけます。ReactではなくてVueを利用してい場合はvueを指定してください。もし何もつけない場合はAlpine.jsがインストールされます。


$ php artisan breeze:install react

breezeインストール後はJavaScriptライブラリのインストールとビルドを行います。


$ npm install && npm run dev

ここまでの設定でReactを利用することができます。先程BladeファイルでAlgoliaの動作確認を行うためweb.phpファイルにルーティングを設定しましたがBreezeのインストールが行われたためweb.phpファイルは上書きされています。BreezeではInertiaを利用するためBladeファイルは利用しません。/usersに関するルーティングを新たにweb.phpファイルに追加します。


Route::get('/users', function () {
    return Inertia::render('Users');
});

Inertiaクラスのrender関数で指定しているUsersはJavaSciptファイルのUser.jsファイルでresource¥js¥Pagesの下に保存して下記を記述します。


import React from "react";

export default function Users(props) {
    return (
        <div className="m-4">
            <h1 className="font-bold text-xl mb-4">ユーザ検索</h1>
        </div>
    );
}

JavaScriptファイルを作成、更新した場合はビルドが必要となるため必ずnpm run watchコマンドを実行しておきます。


$ npm run watch

ビルドが完了後、/usersにアクセスするとユーザ検索の文字列が表示されるはずです。

User.jsファイルの中身を表示
User.jsファイルの中身を表示

InstanceSearchのインストール

ReactでAlogoliaを利用するための検索UIであるInstanceSearchが提供されているのでインストールを行います。


$ npm install algoliasearch react-instantsearch-dom

インストール後に下記を記述します。追加したコードはAlogoliaのドキュメントを参考にしています。


import React from "react";
import algoliasearch from "algoliasearch/lite";
import { InstantSearch, SearchBox, Hits } from "react-instantsearch-dom";

const searchClient = algoliasearch(
    "Application ID",
    "Search-Only API Key"
);

export default function Users(props) {
    return (
        <div className="m-4">
            <h1 className="font-bold text-xl mb-4">ユーザ検索</h1>
            <InstantSearch searchClient={searchClient} indexName="users">
                <SearchBox />
                <Hits />
            </InstantSearch>
        </div>
    );
}

alogoliasearchの引数はApplication IDとSearch-Only API Keyです。設定値はそれぞれ異なるのでAlogoliaで取得した値を設定してください。.envではデータのimportや追加、更新、削除を行うためにAdmin API Keyを利用していましたがReactからは検索のみ行うのでSearch-Only API Keyになります。

ブラウザでアクセスするとusersテーブルに保存されているユーザ情報の一覧が表示されます。InstantSearchウィジットのindexNameのpropsにusersを指定しているためです。ユーザ情報はLaravelを経由せず直接Alogoliaから取得しています。

ユーザ一覧
ユーザ一覧

検索ボックスも表示されているので文字列”山口”を入力すると山口を含むデータが表示されます。

検索を実行
検索を実行

React上でAlogliaを使って検索を行うことができるようになりました。

表示内容の整形

そのままの状態ではオブジェクトとして検索結果が表示されているので必要な情報だけ表示できるように設定を行います。Hitsウィジットに検索結果が表示されますかpropsのhitComponentを設定することで表示させたい内容に変更することができます。


<Hits hitComponent={Hit} />

名前とメールアドレスのみ表示させたい場合はhitComponentに指定した関数Hitを追加します。


const Hit = ({ hit }) => (
    <p>
        {hit.name}/{hit.email}
    </p>
);

再度ブラウザで確認すると以下のような表示に変わります。

必要な情報のみ表示
必要な情報のみ表示

デベロッパーツールで確認するとais-Hits-list, ais-Hits-itemなどのクラス名が付けられています。

classを確認
classを確認

独自のタグやclassをつけるためにHitsウィジットをカスタマイズすることが可能です。

Hitsウィジットのカスタマイズ

検索から取得したデータの表示に対してタグやclass名など独自のものを付与したい場合にHitsウィジットをカスタマイズすることができます。connectHitsをimportとして引数に表示させたい内容を含む関数を指定することで新しいCustomHistsを作成して表示させています。下記ではclassの設定を無くし、olタグを使っています。


import React from "react";
import algoliasearch from "algoliasearch/lite";
import {
    InstantSearch,
    SearchBox,
    connectHits,
} from "react-instantsearch-dom";

const searchClient = algoliasearch(
    "Application ID",
    "Search-Only API Key"
);

const Hits = ({ hits }) => (
    <ol>
        {hits.map((hit) => (
            <li key={hit.objectID}>
                {hit.name}/{hit.email}
            </li>
        ))}
    </ol>
);

const CustomHits = connectHits(Hits);

export default function Users(props) {
    return (
        <div className="m-4">
            <h1 className="font-bold text-xl mb-4">ユーザ検索</h1>
            <InstantSearch searchClient={searchClient} indexName="users">
                <SearchBox />
                <CustomHits />
            </InstantSearch>
        </div>
    );
}

ブラウザで見てもclassに対してCSSを適用していないため何も変化が内容に見えるかもしれません。

必要な情報のみ表示
必要な情報のみ表示

デベロッパーツールで確認すると指定したタグolに代わり、classがなくなりカスタマイズで設定した通りになっていることが確認できます。

カスタマイズ後のHitsコンポーネント
カスタマイズ後のHitsコンポーネント