使用 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,請確保配置適用於 Linux 的 Windows 子系統 (WSL)。

如果使用 WSL,請在終端中執行以下命令以設置首選 Linux 發行版。

 wsl -s ubuntu

接下來,導航到計算機上您要放置項目的位置。 Laravel-Scout 腳本會在這裡生成一個項目目錄。 在下面的示例中,Laravel-Scout 腳本將在桌面目錄中創建一個目錄。

 cd /desktop

運行以下命令以執行 Laravel-Scout 腳本。 它將使用必要的樣板代碼搭建一個 Dockerized 應用程序。

 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配置文件發佈到應用程序的配置目錄。

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

現在,修改樣板.env文件以包含SCOUT_QUEUE布爾值。

SCOUT_QUEUE值將允許 Scout 對操作進行排隊,從而提供更好的響應時間。 沒有它,像 Meil​​isearch 這樣的 Scout 驅動程序將不會立即反映新記錄。

 SCOUT_QUEUE=true

此外,修改.env文件中的DB_HOST變量以指向您的本地主機,以便在 Docker 容器中使用 MySQL 數據庫。

 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 儀表板來管理他們的搜索索引和一個強大的 API,您可以使用您首選的編程語言通過軟件開發工具包 (SDK) 訪問該 API。

在 Laravel 應用程序中,您將使用 PHP 的 Algolia 客戶端包。

如何設置 Algolia

首先,您必須為您的應用程序安裝 Algolia PHP 搜索客戶端包。

執行下面的命令。

 composer require algolia/algoliasearch-client-php

接下來,您必須在.env文件中設置來自 Algolia 的應用程序 ID 和秘密 API 密鑰憑據。

使用您的 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');

上面的代碼在應用程序中定義了兩個路由。 /trains-lists路線的GET請求列出了所有存儲的列車數據。 /create-item路線的POST請求創建新的列車數據。

如何創建應用程序視圖

resources/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 代碼包含一個帶有輸入字段的表單元素和一個用於在將火車保存到數據庫之前鍵入火車標題的按鈕。 該代碼還有一個 HTML 表,顯示數據庫中火車條目的idtitlecreated_atupdated_at詳細信息。

如何使用 Algolia 搜索

要查看該頁面,請從您的 Web 瀏覽器導航到 http://127.0.0.1:8000/trains-lists。

查看火車列表頁面中顯示的火車模型數據
訓練模型數據

數據庫當前為空,因此您需要在輸入字段中輸入演示列車的標題,然後單擊“創建新列車”進行保存。

插入新的列車條目
插入新的列車條目

要使用搜索功能,請將任何保存的火車標題中的關鍵字輸入到“輸入搜索標題”輸入字段中,然後單擊“搜索”

如下圖所示,只會顯示標題中包含關鍵字的搜索條目。

使用搜索功能查找火車條目
使用搜索功能查找火車條目

美力搜索與 Laravel Scout

Meilisearch 是一個開源搜索引擎,專注於速度、性能和改進的開發人員體驗。 它與 Algolia 共享多項功能,使用相同的算法、數據結構和研究——但使用不同的編程語言。

開發人員可以在其本地或云基礎架構中創建和自行託管 Meil​​isearch 實例。 Meilisearch 還為希望在不管理其基礎架構的情況下使用該產品的開發人員提供類似於 Algolia 的 beta 雲服務。

在本教程中,您已經在 Docker 容器中運行了 Meil​​isearch 的本地實例。 您現在將擴展 Laravel Scout 功能以使用 Meil​​isearch 實例。

要將美麗搜索添加到 Laravel 應用程序,請在您的項目終端中運行以下命令。

 composer require meilisearch/meilisearch-php

接下來,您需要修改.env文件中的 Meil​​isearch 變量來配置它。

.env文件中的SCOUT_DRIVERMEILISEARCH_HOSTMEILISEARCH_KEY變量替換為以下變量。

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

SCOUT_DRIVER鍵指定 Scout 應該使用的驅動程序,而MEILISEARCH_HOST表示運行 Meil​​isearch 實例的域。 雖然在開發過程中不需要,但建議在生產中添加MEILISEARCH_KEY

注意:使用美力搜索作為首選驅動程序時,請註釋掉 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 命令將 Explorer 安裝到項目中。

 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, ]; } }

使用上面添加的代碼,您現在可以使用 Explorer 在Train模型中搜索文本。

Laravel + Scout = 快速、健壯、乾淨的全文搜索集成。 構建一個演示應用程序並使用本指南進行試用️ 點擊鳴叫

概括

對於 PHP 開發人員,Laravel 和 Scout 等附加組件可以輕而易舉地集成快速、強大的全文搜索功能。 借助 Database Engine、Collection Engine 以及 Meil​​isearch 和 Elasticsearch 的功能,您可以與應用程序的數據庫進行交互,並在短短幾毫秒內實現高級搜索機制。

無縫管理和更新您的數據庫意味著您的用戶可以獲得最佳體驗,同時您的代碼保持乾淨高效。

借助我們的應用程序和數據庫託管解決方案,Kinsta 是滿足您所有現代 Laravel 開發需求的一站式商店。 第一個 20 美元由我們承擔。