tomtruyen / fuzzyness
一个基于 tomtruyen/Fuzzyness 的提供伪模糊搜索的 Laravel 数据库查询的包。
Requires
- php: ^7.4|^8.0
Requires (Dev)
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.0
README
Fuzzyness
本包基于 mattkingshott 的 "Quest"。
有何不同?
- Fuzzyness 不会跟踪所有 "whereFuzzy" 调用的总 "模糊得分"。
- 原因:不跟踪总模糊得分可以大大加快在拥有 100k+ 条记录的数据库中的查询速度。缺点是内置的按总模糊得分排序功能不存在。
- 可添加自定义匹配器列表
- 可选使用预设匹配器的完整列表或精简版本
关于包
此包可以启用 Laravel 数据库和 Eloquent 查询中的伪模糊搜索。由于其模式匹配方法,它仅支持 MySQL 或 MariaDB,尽管我也欢迎任何支持类似 Postgres 数据库的 PR。
此库的大部分内容基于 Tom Lingham 为现在已废弃的 Laravel Searchy 包所做的出色工作。如果您想了解模糊搜索的工作原理的背景,请查看该项目的说明。
安装
使用 composer 拉取包
composer require tomtruyen/Fuzzyness
用法
Fuzzyness 自动注册一个包含多个宏的服务提供者。然后,这些宏附加到底层的 Illuminate\Database\Query\Builder
类。
过滤结果
您可以通过调用 whereFuzzy
方法执行模糊搜索。此方法接受三个参数。第一个是字段名称,第二个是用于搜索的值,例如,第三个是 "extended"(默认:false)。Extended 使用所有预构建的匹配器,但比非扩展版本慢,但为了获得更具体或更准确的结果,建议将其设置为 true
DB::table('users') ->whereFuzzy('name', 'jd', false) // matches John Doe ->first(); User::whereFuzzy('name', 'jd', false) // matches John Doe ->first();
您也可以通过链式调用多个 whereFuzzy
方法调用在多个列上执行模糊搜索
User::whereFuzzy('name', 'jd', false) // matches John Doe ->whereFuzzy('email', 'gm', false) // matches @gmail.com ->first();
您还可以选择传递自己的 "Matchers" 列表,如果您想使用自定义匹配器或自定义现有匹配器的列表。
注意:您还必须传递当字段与匹配器匹配时的得分
DB::table('users') ->whereCustomFuzzy('name', 'jd', [StartOfWordsMatcher::class => 35]) // matches John Doe ->first(); User::whereCustomFuzzy('name', 'jd', [StartOfWordsMatcher::class => 35]) // matches John Doe ->first();
预设匹配器及其得分的列表
array $matchers = [ ExactMatcher::class => 100, StartOfStringMatcher::class => 50, AcronymMatcher::class => 42, ConsecutiveCharactersMatcher::class => 40, StartOfWordsMatcher::class => 35, StudlyCaseMatcher::class => 32, InStringMatcher::class => 30, TimesInStringMatcher::class => 8, ];
排序结果
当使用 Fuzzyness 时,将在您的搜索结果中包含一个 'relevance_*'
列。这里的 *
是通配符,将被替换为您正在搜索的字段名称,例如。
User::whereFuzzy('email', 'gm') // relevance_email
此列包含记录在应用每个模糊搜索模式匹配器后收到的得分。得分越高,记录与搜索词的匹配度越高。
当然,您会希望按得分排序结果,以便得分最高的记录首先出现。为了简化这个过程,Fuzzyness 包含一个 orderByFuzzy
辅助方法,该方法包装相关的 orderBy
子句
User::whereFuzzy('name', 'jd') ->orderByFuzzy('name') ->first(); // Equivalent to: User::whereFuzzy('name', 'jd') ->orderBy('relevance_name', 'desc') ->first();
如果您正在跨多个字段进行搜索,可以向 orderByFuzzy
方法提供一个 array
User::whereFuzzy('name', 'jd') ->whereFuzzy('email', 'gm') ->orderByFuzzy(['name', 'email']) ->first(); // Equivalent to: User::whereFuzzy('name', 'jd') ->orderBy('relevance_name', 'desc') ->orderBy('relevance_email', 'desc') ->first();
限制
无法使用paginate
方法,因为模糊搜索时,相关性字段被省略了。Laravel在获取需要用于LengthAwarePaginator
的记录数时,会执行一个二级查询,而这些字段没有被包含在内。然而,您可以无障碍地使用simplePaginate
方法,或者结合使用skip
和take
。在很多情况下,这仍然是一个更好的选择,尤其是在处理大量数据集时,因为当翻页数过多时,paginate
方法会变得很慢。
贡献
感谢您考虑为Fuzzyness做出贡献。您欢迎提交包含改进的PR,但如果这些改进是实质性的,请确保也包含相应的测试或测试。
支持项目
如果您想支持Fuzzyness的开发,请考虑赞助我。非常感谢!
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。