highsolutions / laravel-searchy
Laravel Searchy 通过模糊搜索、基本字符串匹配、Levenshtein 距离等方式,简化用户驱动的搜索。
Requires
- php: ^5.5.9 || ^7.0 || ^8.0 || ^8.1 || ^8.2 || ^8.3
- illuminate/support: 5.*|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0
Requires (Dev)
- orchestra/testbench: 3.*|4.*|5.*|6.*|7.*|8.*|9.*|10.*
- phpunit/phpunit: 6.*|7.*|8.*|9.*|10.*|11.*
README
Laravel-Searchy
轻松实现数据库搜索
Searchy 是一个易于使用、轻量级的 Laravel 扩展包,只支持 MySQL,它可以轻松有效地在模型数据上运行用户驱动的搜索。它使用伪模糊搜索和其他加权机制,具体取决于您启用的搜索驱动程序。它不需要在服务器上安装其他软件(因此可能比专用搜索程序略慢),但可以在几分钟内设置并运行。
!! Laravel 4 !!
寻找 Laravel 4 兼容的 Searchy?请检查原始存储库的 1.0 分支
https://github.com/TomLingham/Laravel-Searchy/tree/1.0
安装
将 "highsolutions/laravel-searchy" : "^11.0"
添加到您的 composer.json 文件中的 require
部分
"require": { "highsolutions/laravel-searchy" : "^11.0" }
在您的终端中运行 composer update
以将包拉入您的 vendors 文件夹。
支持 Laravel 6, 7, 8, 9, 10, 11。
使用方法
要使用 Searchy,您可以利用魔法方法。
如果您正在搜索 users
表中用户的名字和电子邮件列/字段,例如,您可以运行
$users = Searchy::users('name', 'email')->query('John Smith')->get();
您也可以这样写
$users = Searchy::search('users')->fields('name', 'email')->query('John Smith')->get();
在这种情况下,将您想要搜索的列传递给 fields()
方法。
这两个示例都返回包含您搜索结果的 Object 数组。如果您想要对结果进行进一步操作,可以使用 getQuery()
而不是 get()
来返回数据库查询对象实例。
$users = Searchy::search('users')->fields('name', 'email')->query('John Smith') ->getQuery()->having('relevance', '>', 20)->get();
返回结果的限制
要限制您的结果,您可以使用 Laravel 内置的数据库查询构建器方法并链式调用更多方法以缩小结果。
// Only get the top 10 results $users = Searchy::search('users')->fields('name', 'email')->query('John Smith') ->getQuery()->limit(10)->get();
搜索多个列
您还可以向搜索的列/字段列表中添加多个参数。
例如,如果您想搜索用户的名字、电子邮件地址和用户名,您可能会运行
$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
别名列,无论在此处输入什么。
如何获取 Laravel Eloquent 集合
将搜索结果转换为 Laravel Eloquent 模型集合超出了此项目的范围。但是,一个简单的方法是使用 Eloquent 的 hydrate()
方法。
\App\User::hydrate(Searchy::users('name', 'email')->query('Andrew')->get());
此方法从纯数组创建模型集合。这正是我们的情况,因为 Searchy 的结果是作为数组提供的,使用 hydrate
,我们将它们转换为 User
模型的实例。
支持 Unicode 字符
如果您因为搜索数据中包含Unicode字符而导致返回结果出现问题,可以使用FuzzySearchUnicodeDriver
。
请注意:在将字符串插入到原始MySQL语句之前,FuzzySearchUnicodeDriver
不会对传入的字符串进行净化。您必须首先自行净化字符串,否则可能会使您的应用程序面临SQL注入攻击。请务必注意。
使用方法,首先按照说明发布您的配置文件(php artisan vendor:publish
),并将默认驱动从fuzzy
更改为ufuzzy
。
return [ 'default' => 'ufuzzy', ... ]
配置
您可以将配置文件发布到app
目录,并通过运行php artisan vendor:publish
来覆盖设置,将配置复制到您的config文件夹中的searchy.php
。
您可以在配置文件中设置用于搜索的默认驱动。当前可用的选项有:fuzzy
、simple
和levenshtein
。
您还可以在执行搜索时使用以下语法覆盖这些方法
Searchy::driver('fuzzy')->users('name')->query('Batman')->get();
驱动程序
Searchy利用“驱动程序”来处理指定字段的各种匹配条件。
驱动程序简单地说是一组指定的“匹配器”,这些匹配器基于特定条件匹配字符串。
目前只有三个驱动程序:简单、模糊和Levenshtein(实验性)。
简单搜索驱动程序
简单搜索驱动程序仅使用3个匹配器,每个匹配器都有最适合我的测试环境的相应乘数。
protected $matchers = [ 'TomLingham\Searchy\Matchers\ExactMatcher' => 100, 'TomLingham\Searchy\Matchers\StartOfStringMatcher' => 50, 'TomLingham\Searchy\Matchers\InStringMatcher' => 30, ];
模糊搜索驱动程序
模糊搜索驱动程序是一组匹配器,设置如下。乘数是我使用的,但您可以根据需要更改这些乘数或创建自己的驱动程序,使用相同的匹配器并更改乘数以适应。
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搜索驱动程序使用Levenshtein距离来计算字符串之间的“距离”。它需要您在MySQL中有一个类似以下存储过程的存储过程:levenshtein(string1, string2)
。在res
文件夹中有一个合适的函数的SQL文件 - 您可以自由使用这个函数。
protected $matchers = [ 'TomLingham\Searchy\Matchers\LevenshteinMatcher' => 100 ];
匹配器
ExactMatcher
匹配精确字符串并应用高乘数,将任何精确匹配项置于顶部。
StartOfStringMatcher
匹配以搜索字符串开头的字符串。例如,搜索“hel”会匹配“Hello World”或“helping hand”。
AcronymMatcher
匹配类似于首字母缩略词的字符串,但不返回大写字母开头的匹配项。例如,搜索“fb”会匹配“foo bar”或“Fred Brown”,但不匹配“FreeBeer”。
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'会匹配;“我希望那只猫抓住了那只老鼠”(3倍乘数)或“谢谢,太棒了!”(1倍乘数)
LevenshteinMatcher
见 Levenshtein 驱动器
扩展
驱动程序
自己实现搜索驱动器非常简单。只需创建一个继承自TomLingham\Searchy\SearchDrivers\BaseSearchDriver
的类,并添加一个名为$matchers
的属性,其值为匹配器类数组和每个匹配器的乘数。您可以选择Searchy已包含的类,或者创建自己的类。
匹配器
要创建自己的匹配器,您可以创建一个继承自TomLingham\Searchy\Matchers\BaseMatcher
的类,并为简单的匹配器重写formatQuery
方法,以返回在需要位置带有%
通配符的字符串。对于更高级的扩展,您可能需要重写buildQuery
方法以及其他方法。
原作者
原作者是Tom Lingham,他已经停止维护这个仓库。我们已经将其分叉以支持新的Laravel版本。