# 模型全文檢索 ## 前言 > [hyperf/scout](https://github.com/hyperf/scout) 衍生於 [laravel/scout](https://github.com/laravel/scout),我們對它進行了一些協程化改造,但保持了相同的 API。在這裏感謝一下 Laravel 開發組,實現瞭如此強大好用的組件。本文檔部分節選自 Laravel China 社區組織翻譯的 Laravel 官方文檔。 Hyperf/Scout 為模型的全文搜索提供了一個簡單的、基於驅動程序的解決方案。使用模型觀察員,Scout 會自動同步你的搜索索引和模型記錄。 目前,Scout 自帶了一個 Elasticsearch 驅動;而編寫自定義驅動程序很簡單,你可以自由地使用自己的搜索實現來擴展 Scout。 ## 安裝 ### 引入組件包和 Elasticsearch 驅動 ```bash composer require hyperf/scout composer require hyperf/elasticsearch ``` Scout 安裝完成後,使用 vendor:publish 命令來生成 Scout 配置文件。這個命令將在你的 config 目錄下生成一個 scout.php 配置文件。 ```bash php bin/hyperf vendor:publish hyperf/scout ``` 最後,在你要做搜索的模型中添加 Hyperf\Scout\Searchable trait。這個 trait 會註冊一個模型觀察者來保持模型和所有驅動的同步: ```php ### 配置可搜索的數據 默認情況下,「索引」會從模型的 `toArray` 方法中讀取數據來做持久化。如果要自定義同步到搜索索引的數據,可以覆蓋模型上的 `toSearchableArray` 方法: toArray(); // Customize array... return $array; } } ## 索引 ### 批量導入 如果你想要將 Scout 安裝到現有的項目中,你可能已經有了想要導入搜索驅動的數據庫記錄。使用 Scout 提供的命令 `import` 把所有現有記錄導入到搜索索引裏: php bin/hyperf.php scout:import "App\Post" ### 添加記錄 當你將 Trait `Hyperf\Scout\Searchable` 添加到模型中,你需要做的是 `save` 一個模型實例,它就會自動添加到你的搜索索引。更新索引操作將會在協程結束時進行,不會堵塞請求。 $order = new App\Order; // ... $order->save(); #### 批量添加 如果你想通過模型查詢構造器將模型集合添加到搜索索引中,你也可以在模型查詢構造器上鍊式調用 `searchable` 方法。`searchable` 會把構造器的查詢結果分塊並且將記錄添加到你的搜索索引裏。 // 使用模型查詢構造器增加... App\Order::where('price', '>', 100)->searchable(); // 使用模型關係增加記錄... $user->orders()->searchable(); // 使用集合增加記錄... $orders->searchable(); `searchable` 方法可以被看做是「更新插入」的操作。換句話説,如果模型記錄已經在你的索引裏了,它就會被更新。如果搜索索引中不存在,則將其添加到索引中。 ### 更新記錄 要更新可搜索的模型,只需要更新模型實例的屬性並將模型 `save` 到數據庫。Scout 會自動將更新同步到你的搜索索引中: $order = App\Order::find(1); // 更新 order... $order->save(); 你也可以在模型查詢語句上使用 `searchable` 方法來更新一個模型的集合。如果這個模型不存在你檢索的索引裏,就會被創建: // 使用模型查詢語句更新... App\Order::where('price', '>', 100)->searchable(); // 你也可以使用模型關係更新... $user->orders()->searchable(); // 你也可以使用集合更新... $orders->searchable(); ### 刪除記錄 簡單地使用 `delete` 從數據庫中刪除該模型就可以移除索引裏的記錄。這種刪除形式甚至與軟刪除的模型兼容: $order = App\Order::find(1); $order->delete(); 如果你不想在刪除記錄之前檢索模型,可以在模型查詢實例或集合上使用 `unsearchable` 方法: // 通過模型查詢刪除... App\Order::where('price', '>', 100)->unsearchable(); // 通過模型關係刪除... $user->orders()->unsearchable(); // 通過集合刪除... $orders->unsearchable(); ### 暫停索引 你可能需要在執行一批模型操作的時候,不同步模型數據到搜索索引。此時你可以使用協程安全的 `withoutSyncingToSearch` 方法來執行此操作。這個方法接受一個立即執行的回調。該回調中所有的操作都不會同步到模型的索引: App\Order::withoutSyncingToSearch(function () { // 執行模型動作... }); ## 搜索 你可以使用 `search` 方法來搜索模型。`search` 方法接受一個用於搜索模型的字符串。你還需在搜索查詢上鍊式調用 `get` 方法,才能用給定的搜索語句查詢與之匹配的模型模型: $orders = App\Order::search('Star Trek')->get(); Scout 搜索返回模型模型的集合,因此你可以直接從路由或控制器返回結果,它們會被自動轉換成 JSON 格式: Route::get('/search', function () { return App\Order::search([])->get(); }); 如果你想在它們返回模型模型前得到原結果,你應該使用`raw` 方法: $orders = App\Order::search('Star Trek')->raw(); 搜索查詢通常會在模型的 [`searchableAs`](#configuring-model-indexes) 方法指定的索引上執行。當然,你也可以使用 `within` 方法指定應該搜索的自定義索引: $orders = App\Order::search('Star Trek') ->within('tv_shows_popularity_desc') ->get(); ### Where 語句 Scout 允許你在搜索查詢中增加簡單的「where」語句。目前,這些語句只支持基本的數值等式檢查,並且主要是用於根據擁有者的 ID 進行的範圍搜索查詢。由於搜索索引不是關係型數據庫,因此當前不支持更高級的「where」語句: $orders = App\Order::search('Star Trek')->where('user_id', 1)->get(); ### 分頁 除了檢索模型的集合,你也可以使用 `paginate` 方法對搜索結果進行分頁。這個方法會返回一個就像 [傳統的模型查詢分頁](/zh-cn/db/paginator) 一樣的 `Paginator` 實例: $orders = App\Order::search('Star Trek')->paginate(); 你可以通過將數量作為第一個參數傳遞給 `paginate` 方法來指定每頁檢索多少個模型: $orders = App\Order::search('Star Trek')->paginate(15); 獲取到檢索結果後,就可以使用喜歡的模板引擎來渲染分頁鏈接從而顯示結果,就像傳統的模型查詢分頁一樣: