Laravel8 Scout Search Example

Laravel8 Scout Search Example

效果

懶得看詳細介紹可直接跳至簡單完整範例,但必須先安裝完成相關套件安裝及申請Algolia專案

介紹

Laravel Scout提供了一個簡單的、基於驅動程序的解決方案,用於為您的Eloquent 模型添加全文搜索。使用模型觀察器,Scout 會自動使您的搜索索引與您的 Eloquent 記錄保持同步。

目前,Scout 附帶AlgoliaMeiliSearch驅動程序。此外,Scout 包含一個“集合”驅動程序,專為本地開發使用而設計,不需要任何外部依賴項或第三方服務。此外,編寫自定義驅動程序很簡單,您可以使用自己的搜索實現自由擴展 Scout

安裝

安裝Laravel Scout

composer require laravel/scout

發佈配置

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

最後,將Laravel\Scout\Searchable特徵添加到您希望使其可搜索的模型中。此特徵將註冊一個模型觀察者,該觀察者將自動使模型與您的搜索驅動程序保持同步:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Product extends Model
{
    use Searchable;
}

申請Algolia

algolia申請新的專案

選擇香港區域

複製專案ID以及SECRET

使用Algolia驅動

使用 Algolia 驅動程序時,您應該在config/scout.php中配置您的 Algolia id和secret key 。配置憑據後,您還需要通過 Composer 包管理器安裝 Algolia PHP SDK:

composer require algolia/algoliasearch-client-php

.env檔案填入剛剛複製的專案id以及key

ALGOLIA_APP_ID=
ALGOLIA_SECRET=

queue

運行queue將允許 Scout 將您的模型信息同步到您的搜索索引的操作進行排隊,從而為您的應用程序的 Web 界面提供更好的響應時間。

配置隊列驅動程序後,將配置文件中的queue選項值設置config/scout.php為true:

SCOUT_QUEUE=true

配置

配置模型索引

每個 Eloquent 模型都與給定的搜索“索引”同步,該索引包含該模型的所有可搜索記錄。換句話說,您可以將每個索引視為一個 MySQL 表。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Product extends Model
{
    use Searchable;

    /**
     * Get the name of the index associated with the model.
     *
     * @return string
     */
    public function searchableAs()
    {
        // 在Algolia Index的名稱
        return 'productts_index';
    }
}

配置可搜索數據

默認情況下,toArray給定模型的整個表單將被持久化到其搜索索引。如果您想自定義與搜索索引同步的數據,您可以覆蓋toSearchableArray模型上的方法:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;

    /**
     * Get the indexable data array for the model.
     *
     * @return array
     */
    public function toSearchableArray()
    {
        $array = $this->toArray();

        // Customize the data array...

        // 有一對一關聯可以這樣寫
        $array['user'] = $this->user->name;

        // 可以自訂義欄位

        return $array;
    }
}

配置模型 ID

默認情況下,Scout 將使用模型的主鍵作為存儲在搜索索引中的模型的唯一 ID/鍵。如果您需要自定義此行為,您可以覆蓋模型上的getScoutKey和getScoutKeyName方法:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class User extends Model
{
    use Searchable;

    /**
     * Get the value used to index the model.
     *
     * @return mixed
     */
    public function getScoutKey()
    {
        return $this->email;
    }

    /**
     * Get the key name used to index the model.
     *
     * @return mixed
     */
    public function getScoutKeyName()
    {
        return 'email';
    }
}

本地開發

雖然您在本地開發過程中可以自由使用 AlgoliaMeiliSearch 搜索引擎,但您可能會發現使用“collection”引擎更方便。collection引擎將對您現有數據庫中的結果使用“where”子句和收集過濾,以確定適用於您的查詢的搜索結果。使用此引擎時,沒有必要為您的可搜索模型“編制索引”,因為它們只會從您的本地數據庫中檢索。

要使用collection引擎,您可以簡單地將SCOUT_DRIVER環境變量的值設置為collection,或者直接在應用程序的scout配置文件中指定驅動程序:

SCOUT_DRIVER=collection

一旦您將集合驅動程序指定為首選驅動程序,您就可以開始對您的模型執行搜索查詢。使用收集引擎時,不需要搜索引擎索引,例如AlgoliaMeiliSearch 索引所需的索引。

索引

批量導入索引

使用scout:importArtisan 指令,該指令將所有現有記錄導入到您的搜索索引中:

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

flush命令可用於從搜索索引中刪除模型的所有記錄:

php artisan scout:flush "App\Models\Post"

修改導入查詢

如果您想修改用於檢索所有模型以進行批量導入的查詢,您可以makeAllSearchableUsing在模型上定義一個方法。這是在導入模型之前添加可能需要的任何急切關係加載的好地方:

/**
 * Modify the query used to retrieve models when making all of the models searchable.
 *
 * @param  \Illuminate\Database\Eloquent\Builder  $query
 * @return \Illuminate\Database\Eloquent\Builder
 */
protected function makeAllSearchableUsing($query)
{
    return $query->with('author');
}

添加記錄

一旦你已經添加了Laravel\Scout\Searchable性狀的模型,所有你需要做的是savecreate模型實例,它會自動被添加到您的搜索索引。如果您已將 Scout 配置為使用隊列,則此操作將由queue在後台執行:

use App\Models\Order;

$order = new Order;

// ...

$order->save();

搜尋

使用該search方法搜索模型。search 方法接受將用於搜索模型的單個字符串。然後,您應該將該get方法鏈接到搜索查詢上,以檢索與給定搜索查詢匹配的 Eloquent 模型:

use App\Models\Order;

$orders = Order::search('Star Trek')->get();

如果您想在將原始搜索結果轉換為 Eloquent 模型之前獲得原始搜索結果,您可以使用以下raw方法:

$orders = Order::search('Star Trek')->raw();

自定義索引

搜索查詢通常在模型searchableAs方法指定的索引上執行。但是,您可以使用該within方法來指定應該搜索的自定義索引:

$orders = Order::search('Star Trek')
    ->within('tv_shows_popularity_desc')
    ->get();

分頁

除了檢索模型集合之外,您還可以使用該paginate方法對搜索結果進行分頁。此方法將返回一個Illuminate\Pagination\LengthAwarePaginator實例,就像您對傳統的 Eloquent 查詢分頁一樣

use App\Models\Order;

$orders = Order::search('Star Trek')->paginate();

您可以通過將數量作為第一個參數傳遞給paginate方法來指定每頁檢索多少模型:

$orders = Order::search('Star Trek')->paginate(15);

檢索結果後,您可以使用Blade顯示結果並呈現頁面鏈接,就像對傳統的 Eloquent 查詢進行分頁一樣:

<div class="container">
    @foreach ($orders as $order)
        {{ $order->price }}
    @endforeach
</div>

{{ $orders->links() }}

當然,如果您想以 JSON 形式檢索分頁結果,您可以直接從路由或控制器返回分頁器實例:

use App\Models\Order;
use Illuminate\Http\Request;

Route::get('/orders', function (Request $request) {
    return Order::search($request->input('query'))->paginate(15);
});

簡單完整範例

.env配置

SCOUT_QUEUE=true
ALGOLIA_APP_ID=YOUR APP_ID
ALGOLIA_SECRET=YOUR SECRET

Product Migration

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('details');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Product Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Product extends Model
{
    use HasFactory, Searchable;

    protected $fillable = ['name', 'details'];

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

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

        return $array;
    }
}

Product Controller

public function index(Request $request)
{
    if ($request->has('keyword')) {
        $products = Product::search($request->keyword)
            ->paginate(5);
    } else {
        $products = Product::paginate(5);
    }
    return view('products', compact('products'));
}

路由web.php

Route::get('/products', 'App\Http\Controllers\ProductController@index')->name('products');

View products.blade.php

<!DOCTYPE html>
<html>
    <head>
        <title>Laravel 使用scount全文檢索範例</title>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body>
        <div class="container">
            <h3 class="text-center">Laravel 使用scount全文檢索範例</h3>
            <form class="form-inline mb-5" method="GET" action="{{ route('products') }}">
                <input type="text" class="form-control" name="keyword">
                <button class="btn btn-outline-secondary" type="submit">搜尋</button>
            </form>
            <table class="table table-bordered">
                <tr>
                    <th width="80px">id</th>
                    <th>名稱</th>
                    <th>介紹</th>
                    <th>創建時間</th>
                </tr>
                @if($products->count())
                    @foreach($products as $key => $product)
                        <tr>
                            <td>{{ $product->id }}</td>
                            <td>{{ $product->name }}</td>
                            <td>{{ $product->details }}</td>
                            <td>{{ $product->created_at->format('d-m-Y') }}</td>
                        </tr>
                    @endforeach
                @endif
            </table>
            {{ $products->links() }}
        </div>
    </body>
</html>

導入索引

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

導入後可以發現Algolia多了相關的索引

run php artisan serve

相關資訊

Laravel scout官方

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!