* * * * *
[TOC]
## 簡介
Laravel Scout 為?[Eloquent 模型](http://www.hmoore.net/tonyyu/laravel_5_6/786272)?全文搜索提供了簡單的,基于驅動的解決方案。通過使用模型觀察者,Scout 會自動同步 Eloquent 記錄的搜索索引。
目前,Scout 自帶一個?[Algolia](https://www.algolia.com/)?驅動;不過,編寫自定義驅動很簡單, 你可以輕松的通過自己的搜索實現來擴展 Scout。
## 安裝
首先,通過 Composer 包管理器來安裝 Scout:
~~~
composer require laravel/scout
~~~
Scout 安裝完成之后,你應該使用?`vendor:publish`?Artisan 命令來生成 Scout 配置文件。這個命令將生成?`scout.php`?配置文件到你的?`config`?目錄:
~~~
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
~~~
最后,在你想要做搜索的模型中添加?`Laravel\Scout\Searchable`?trait。這個 trait 會注冊一個模型觀察者來保持模型和搜索驅動的同步:
~~~
<?php
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Searchable;
}
~~~
### 隊列
雖然不是強制要求使用 Scout,但在使用這個庫之前,強烈建議配置一個?[隊列驅動](http://www.hmoore.net/tonyyu/laravel_5_6/786248)?。運行一個隊列來處理 Scout 將模型信息同步到搜索索引的所有操作,為你應用的 web 接口提供更快的響應時間。
一旦你配置了隊列驅動程序,在你的?`config/scout.php`?配置文件中設置?`queue`?選項的值為`true`:
~~~
'queue' => true,
~~~
### 驅動必要條件
#### Algolia
使用 Algolia 驅動時,需要在?`config/scout.php`?配置文件配置你的 Algolia?`id`?和?`secret`?憑證。配置好憑證之后, 還需要使用 Composer 包管理器安裝 Algolia PHP SDK :
~~~
composer require algolia/algoliasearch-client-php
~~~
## 配置
### 配置模型索引
每個Eloquent模型都是通過給定的搜索「索引」進行同步,該「索引」包含所有可搜索的模型記錄。換句話說,你可以把每一個「索引」設想為一張 MySQL 數據表。默認情況下,每個模型都會被持久化到與模型的「表」名(通常是模型名稱的復數形式)相匹配的索引。你也可以通過覆蓋模型上的?`searchableAs`?方法來自定義模型的索引:
~~~
<?php
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Searchable;
/**
* Get the index name for the model.
*
* @return string
*/
public function searchableAs()
{
return 'posts_index';
}
}
~~~
### 配置可搜索數據
默認情況下,模型以完整的?`toArray`?格式持久化到搜索索引。如果要自定義同步到搜索索引的數據,可以覆蓋模型上的?`toSearchableArray`?方法:
~~~
<?php
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Searchable;
/**
* Get the indexable data array for the model.
*
* @return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
// Customize array...
return $array;
}
}
~~~
## 索引
### 批量導入
如果你想安裝Scout 到已存在的項目中,你可能已經有了想要導入搜索驅動的數據庫記錄。Scout 提供了 Artisan 命令?`import`?用來導入所有已存在的記錄到搜索索引:
~~~
php artisan scout:import "App\Post"
~~~
### 添加記錄
當你將?`Laravel\Scout\Searchable`?trait 添加到模型中,你需要做的就是?`save`?一個模型實例,它將自動被添加到搜索索引。如果你已經將 Scout 配置為?[使用隊列](http://www.hmoore.net/tonyyu/laravel_5_6/786295#_38),那這個操作會在后臺由你的隊列工作進程來執行:
~~~
$order = new App\Order;
// ...
$order->save();
~~~
#### 通過查詢添加
如果你想通過 Eloquent 查詢構造器將模型集合添加到搜索索引中,你也可以在 Eloquent 查詢構造器上鏈式調用?`searchable`?方法。`searchable`?會把構造器的查詢?[結果分塊](http://www.hmoore.net/tonyyu/laravel_5_6/786272#_194)?并且將記錄添加到你的搜索索引里。同樣的,如果你已經配置 Scout 為使用隊列,則所有的數據塊將在后臺由你的隊列工作進程添加:
~~~
// 通過 Eloquent 查詢構造器增加...
App\Order::where('price', '>', 100)->searchable();
// 你也可以通過模型關系增加記錄...
$user->orders()->searchable();
// 你也可以通過集合增加記錄...
$orders->searchable();
~~~
`searchable`?方法可以被看做是「更新插入」的操作。換句話說,如果模型記錄已經在你的索引里了,它就會被更新。如果搜索索引中不存在,則將其添加到索引中。
### 更新記錄
要更新可搜索的模型,只需要更新模型實例的屬性并將模型?`save`?到數據庫。Scout 會自動將更新同步到你的搜索索引中:
~~~
$order = App\Order::find(1);
// Update the order...
$order->save();
~~~
你也可以在 Eloquent 查詢語句上使用?`searchable`?方法來更新一個模型的集合。如果這個模型不存在你檢索的索引里,就會被創建:
~~~
// Updating via Eloquent query...
App\Order::where('price', '>', 100)->searchable();
// You may also update via relationships...
$user->orders()->searchable();
// You may also update via collections...
$orders->searchable();
~~~
### 刪除記錄
簡單地使用?`delete`?從數據庫中刪除該模型就可以移除索引里的記錄。這種刪除形式甚至與?[軟刪除]http://www.hmoore.net/tonyyu/laravel_5_6/786272#_470)?的模型兼容:
~~~
$order = App\Order::find(1);
$order->delete();
~~~
如果你不想在刪除記錄之前檢索模型,可以在 Eloquent 查詢實例或集合上使用?`unsearchable`?方法:
~~~
// Removing via Eloquent query...
App\Order::where('price', '>', 100)->unsearchable();
// You may also remove via relationships...
$user->orders()->unsearchable();
// You may also remove via collections...
$orders->unsearchable();
~~~
### 暫停索引
你可能需要在執行一批 Eloquent 操作的時候,不同步模型數據到搜索索引。此時你可以使用?`withoutSyncingToSearch`方法來執行此操作。這個方法接受一個立即執行的回調。該回調中所有的操作都不會同步到模型的索引:
~~~
App\Order::withoutSyncingToSearch(function () {
// Perform model actions...
});
~~~
### 有條件地搜索模型實例
有時候你可能需要在某些條件下模型是可搜索的。例如,假設你有?`App\Post`?模型可能兩種狀態之一:「草稿」和「發布」。你可能只允許搜索 「發布」過的帖子。為了實現這一點,你可能要在你的模型中定義一個?`shouldBeSearchable`方法:
~~~
public function shouldBeSearchable()
{
return $this->isPublished();
}
~~~
## 搜索
你可以使用?`search`?方法來搜索模型。`search`?方法接受一個用于搜索模型的字符串。你還需在搜索查詢上鏈式調用?`get`?方法,才能用給定的搜索語句查詢與之匹配的 Eloquent 模型:
~~~
$orders = App\Order::search('Star Trek')->get();
~~~
Scout 搜索返回 Eloquent 模型的集合,因此你可以直接從路由或控制器返回結果,它們會被自動轉換成 JSON 格式:
~~~
use Illuminate\Http\Request;
Route::get('/search', function (Request $request) {
return App\Order::search($request->search)->get();
});
~~~
如果你想在它們返回 Eloquent 模型前得到原結果,你應該使用`raw`?方法:
~~~
$orders = App\Order::search('Star Trek')->raw();
~~~
搜索查詢通常會在模型的?[`searchableAs`](http://www.hmoore.net/tonyyu/laravel_5_6/786295#_58)?方法指定的索引上執行。當然,你也可以使用?`within`?方法指定應該搜索的自定義索引:
~~~
$orders = App\Order::search('Star Trek')
->within('tv_shows_popularity_desc')
->get();
~~~
### Where 語句
允許你在搜索查詢中增加簡單的「where」語句。目前,這些語句只支持基本的數值等式檢查,并且主要是用于根據擁有者的 ID 進行的范圍搜索查詢。由于搜索索引不是關系型數據庫,因此當前不支持更高級的「where」語句:
~~~
$orders = App\Order::search('Star Trek')->where('user_id', 1)->get();
~~~
### 分頁
除了檢索模型的集合,你也可以使用?`paginate`?方法對搜索結果進行分頁。這個方法會返回一個就像?[傳統的 Eloquent 查詢分頁](http://www.hmoore.net/tonyyu/laravel_5_6/786262)?一樣的?`Paginator`?實例:
~~~
$orders = App\Order::search('Star Trek')->paginate();
~~~
你可以通過將數量作為第一個參數傳遞給?`paginate`?方法來指定每頁檢索多少個模型:
~~~
$orders = App\Order::search('Star Trek')->paginate(15);
~~~
獲取到檢索結果后,就可以使用?[Blade](http://www.hmoore.net/tonyyu/laravel_5_6/786198)?來渲染分頁鏈接從而顯示結果,就像傳統的 Eloquent 查詢分頁一樣:
~~~
<div class="container">
@foreach ($orders as $order)
{{ $order->price }}
@endforeach
</div>
{{ $orders->links() }}
~~~
### 軟刪除
如果你的索引模型是?[軟刪除](http://www.hmoore.net/tonyyu/laravel_5_6/786272#_470)?,并且你需要搜索軟刪除的模型,設置?`config/scout.php`?配置文件`soft_delete`?選項的值為?`true`:
~~~
'soft_delete' => true,
~~~
當這個配置選項是?`true`的時候, Scout 不會從搜索索引中移除軟刪除模型。相反,它會在索引記錄中設置一個隱藏?`__soft_deleted`?屬性。 然后,在搜索的時候,你可以使用?`withTrashed`?或?`onlyTrashed`?方法檢索軟刪除記錄:
~~~
// 搜索結果包括已刪除的記錄...
$orders = App\Order::withTrashed()->search('Star Trek')->get();
// 搜索結果只包含已刪除的記錄...
$orders = App\Order::onlyTrashed()->search('Star Trek')->get();
~~~
> {tip} 要永久刪除模型可以使用?`forceDelete`?來刪除,Scout 將自動的從搜索索引中移除模型。
## 自定義引擎
#### 寫引擎
如果內置的 Scout 搜索引擎不能滿足你的需求,你可以寫自定義的引擎并且將它注冊到 Scout。你的引擎需要繼承?`Laravel\Scout\Engines\Engine`?抽象類,這個抽象類包含了你自定義的引擎必須要實現的七種方法:
~~~
use Laravel\Scout\Builder;
abstract public function update($models);
abstract public function delete($models);
abstract public function search(Builder $builder);
abstract public function paginate(Builder $builder, $perPage, $page);
abstract public function mapIds($results);
abstract public function map($results, $model);
abstract public function getTotalCount($results);
~~~
在?`Laravel\Scout\Engines\AlgoliaEngine`?類里查看這些方法的實現會對你有較大的幫助。這個類會為你在學習如何在自定義引擎中實現這些方法提供一個好的起點。
#### 注冊引擎
一旦你寫好了自定義引擎,你可以用 Scout 引擎管理的?`extend`?方法將它注冊到 Scout。你只需要從?`AppServiceProvider`?下的?`boot`?方法或者應用中使用的任何一個服務提供器調用?`extend`?方法。舉個例子,如果你寫好了一個?`MySqlSearchEngine`,你可以像這樣去注冊它:
~~~
use Laravel\Scout\EngineManager;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
resolve(EngineManager::class)->extend('mysql', function () {
return new MySqlSearchEngine;
});
}
~~~
引擎注冊后,你可以在?`config/scout.php`?配置文件中指定它為默認的 Scout?`driver`:
~~~
'driver' => 'mysql',
~~~
- 前言
- 翻譯說明
- 發行說明
- 升級指南
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- Homestead
- Valet
- 部署
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- Facades
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全相關
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試相關
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Scout 全文搜索
- Socialite 社會化登錄