1、簡介
Laravel Searchy是一個易上手的、 輕量級的、支援MySQL的Laravel搜尋擴充包,使用該擴充包可以簡單高效的實現基於模型的資料查詢搜尋功能,該擴充包還可以基於你所啟用的搜尋引擎實現模糊搜尋和其它加權機制。此外,不需要伺服器安裝任何其它軟體即可開始使用該擴充包。
註:如果要相容Laravel 4,參考 https://github.com/TomLingham/Laravel-Searchy/tree/1.0
2、安裝
我們使用Composer來安裝該擴充包,在 composer.json 的 require 項中添加如下兩個依賴:
"require": { "tom-lingham/searchy" : "2.*"}
然後運行 composer update 將依賴下載到 vendor 目錄。
安裝完成後需要註冊服務提供者到 config/app.php 的 providers :
TomLingham\Searchy\SearchyServiceProvider::class
順便在 config/app.php 的 aliases 中註冊相應門面:
'Searchy' => TomLingham\Searchy\Facades\Searchy::class
3、使用
如果要搜尋使用者(對應資料表 users )的名字和Email:
$users = Searchy::users('name', 'email')->query('John Smith')->get();
同樣的功能還可以這樣實現:
$users = Searchy::search('users')->fields('name', 'email')->query('John Smith')->get();
在本例中,我們通過 fields 方法傳遞搜尋欄位。
以上代碼都會返回包含搜尋結果的對象數組,如果要返回資料庫查詢對象執行個體可以使用 getQuery() 替代 get() 方法:
$users = Searchy::search('users')->fields('name', 'email')->query('John Smith') ->getQuery()->having('relevance', '>', 20)->get();
查詢多個欄位
例如,你想要搜尋使用者的名字、Email和使用者名稱,可以這樣調用:
$users = Searchy::users('name', 'email', 'username')->query('John Smith')->get();
如果需要動態傳入搜尋欄位,可以以數組形式傳遞參數:
$users = Searchy::users(['name', 'email', 'username'])->query('John Smith')->get();
查詢串連/級聯欄位
有時候你可能需要搜尋級聯欄位,例如,你想要一次性整體返回 first_name 和 last_name ,可以通過兩個冒號來分隔欄位:
$users = Searchy::users('first_name::last_name')->query('John Smith')->get();
虛刪除記錄
預設情況下,虛刪除記錄不會包含到搜尋結果。如果你想要包含虛刪除記錄可以通過在指定表和欄位之後添加 withTrashed() 來實現:
Searchy::users('name')->withTrashed()->query('Batman')->get();
返回指定欄位
你可以指定搜尋要返回的欄位:
$users = Searchy::users('first_name::last_name')->query('John Smith')->select('first_name')->get();// Or you can swap those around...$users = Searchy::users('first_name::last_name')->select('first_name')->query('John Smith')->get();
此外,這裡還會返回別名欄位 relevance ,不管輸入的是什麼。
4、配置
你發行就緒設定檔到 config 目錄以覆蓋預設配置:
php artisan vendor:publish
在產生的設定檔 searchy.php 中可以設定搜尋使用的預設驅動,目前支援 fuzzy 、 simple 和 levenshtein 。
搜尋時還可以使用如下文法動態設定搜尋驅動:
Searchy::driver('fuzzy')->users('name')->query('Batman')->get();
5、搜尋驅動
Searchy使用”驅動“來處理多條件欄位的匹配,簡單來說,驅動就是一個指定分組的”匹配器“,用於基於指定條件匹配字串。目前Searchy只支援三種驅動:Simple、Fuzzy和Levenshtein(實驗性)
Simple
Simple搜尋驅動只使用了3個匹配器,每個匹配器都有一個相關的乘法因子以便最好匹配我的測試環境:
protected $matchers = [ 'TomLingham\Searchy\Matchers\ExactMatcher' => 100, 'TomLingham\Searchy\Matchers\StartOfStringMatcher' => 50, 'TomLingham\Searchy\Matchers\InStringMatcher' => 30,];
Fuzzy
Fuzzy搜尋驅動是另外一個匹配器組合。這裡面的乘法因子都是我用過的,你也可以手動修改它們:
protected $matchers = [ 'TomLingham\Searchy\Matchers\ExactMatcher' => 100, 'TomLingham\Searchy\Matchers\StartOfStringMatcher' => 50, 'TomLingham\Searchy\Matchers\AcronymMatcher' => 42, 'TomLingham\Searchy\Matchers\ConsecutiveCharactersMatcher' => 40, 'TomLingham\Searchy\Matchers\StartOfWordsMatcher' => 35, 'TomLingham\Searchy\Matchers\StudlyCaseMatcher' => 32, 'TomLingham\Searchy\Matchers\InStringMatcher' => 30, 'TomLingham\Searchy\Matchers\TimesInStringMatcher' => 8,];
Levenshtein
Levenshtein搜尋驅動使用Levenshetein Distance(一種字串相似性演算法)來計算字串之間的“距離”,這要求你在MySQL中有一個與 levenshtein( string1, string2 ) 類似的預存程序(這個預存程序在擴充包源碼 res 目錄下的SQL檔案中):
protected $matchers = [ 'TomLingham\Searchy\Matchers\LevenshteinMatcher' => 100];
6、匹配器
ExactMatcher
完全符合
StartOfStringMatcher
匹配字串開頭是否一致,比如“hel”和“Hello World”
AcronymMatcher
匹配字串縮寫,例如“fb”和“foo bar”或“Fred Brown”
ConsecutiveCharactersMatcher
匹配字串是否包含一致的連續字元,此外還會計算匹配字元所佔百分比並應用相應的乘法因子,例如搜尋“fba”會匹配“foo bar”或者“Afraid of bats”,而不會匹配“fabulous”
StartOfWordsMatcher
匹配字串開頭的單詞是否一致,例如,“jo ta”與“John Taylor”或者“Joshua B. Takeshi”
StudlyCaseMatcher
駝峰式匹配,例如“hp”和“HtmlServiceProvider”或者“HashParser”,但不會匹配“hasProvider”
InStringMatcher
字串包含匹配,例如“smi”和“John Smith”或者“Smiley Face”
TimesInStringMatcher
字串包含次數匹配,例如搜尋“tha”會匹配“I hope that that cat has caught that mouse”(3×)或者“Thanks, it was great!”(1×)
LevenshteinMatcher
參考Levenshtein Driver。
7、擴充
驅動
實現自己的搜尋驅動很簡單,只需要建立一個繼承自 TomLingham\Searchy\SearchDrivers\BaseSearchDriver 的類並添加一個 $matchers 屬性數組即可。
匹配器
要建立自己的匹配器,可以建立一個繼承自 TomLingham\Searchy\Matchers\BaseMatcher 的類並重寫 formatQuery 方法,然後返回一個在指定位置以%萬用字元格式化的字串。要實現更加進階的擴充需要重寫 buildQuery 方法。