mattkingshott / quest
Requires
- php: ^7.4|^8.0
Requires (Dev)
- orchestra/testbench: ^8.0
- phpunit/phpunit: ^10.0
README
此包可在 Laravel 数据库和 Eloquent 查询中启用伪模糊搜索。由于其模式匹配方法,它只支持 MySQL 或 MariaDB,尽管我欢迎任何 PR 以启用对类似 Postgres 的数据库的支持。
此库的大部分基于 Tom Lingham 为已废弃的 Laravel Searchy 包所做的出色工作。如果您对模糊搜索的工作原理感兴趣,请查看该项目的说明文档。
安装
使用 composer 拉取此包
composer require caneara/quest
使用方法
Quest 自动注册一个服务提供者,其中包含多个宏。然后,这些宏被附加到底层的 Illuminate\Database\Query\Builder
类。
过滤结果
您可以通过调用 whereFuzzy
方法来执行模糊搜索。此方法接受两个参数。第一个是字段名。第二个是用于搜索的值,例如。
DB::table('users') ->whereFuzzy('name', 'jd') // matches John Doe ->first(); User::whereFuzzy('name', 'jd') // matches John Doe ->first();
您还可以通过链式调用多个 whereFuzzy
方法来在多个列上执行模糊搜索
User::whereFuzzy('name', 'jd') // matches John Doe ->whereFuzzy('email', 'gm') // matches @gmail.com ->first();
您还可以通过 orWhereFuzzy
方法调用在多个列上执行搜索
User::whereFuzzy(function ($query) { $query->orWhereFuzzy('name', 'jd'); // matches John Doe $query->orWhereFuzzy('email', 'gm'); // matches @gmail.com })->first();
排序结果
当使用 Quest 时,您的搜索结果将包含一个 'fuzzy_relevance_*'
列。其中的 *
是通配符,将被替换为您正在搜索的字段名,例如。
User::whereFuzzy('email', 'gm') // fuzzy_relevance_email
此列包含记录在应用了模糊搜索模式匹配器后获得的分数。分数越高,记录与搜索项的匹配度越接近。
当然,您会希望根据分数对结果进行排序,以便具有最高分数的记录首先出现。为了简化这一点,Quest 包含一个 orderByFuzzy
辅助方法,该方法包装相关的 orderBy
子句
User::whereFuzzy('name', 'jd') ->orderByFuzzy('name') ->first(); // Equivalent to: User::whereFuzzy('name', 'jd') ->orderBy('fuzzy_relevance_name', 'desc') ->first();
如果您正在跨多个字段搜索,可以向 orderByFuzzy
方法提供一个 array
User::whereFuzzy('name', 'jd') ->whereFuzzy('email', 'gm') ->orderByFuzzy(['name', 'email']) ->first(); // Equivalent to: User::whereFuzzy('name', 'jd') ->orderBy('fuzzy_relevance_name', 'desc') ->orderBy('fuzzy_relevance_email', 'desc') ->first();
应用最小阈值
当使用 Quest 时,将在 _fuzzy_relevance_
列中为每个记录分配一个总体分数。此分数以介于 0 和 295 之间的 integer
表示。
请注意,
fuzzy_relevance
分数不会除以列数。因此,如果两个字段完全匹配,它可能高达 590。
您可以使用 withMinimumRelevance()
方法强制执行最小分数,以限制结果。设置更高的分数将返回更少但可能更相关的结果。
// Before User::whereFuzzy('name', 'jd') ->having('_fuzzy_relevance_', '>', 70) ->first(); // After User::whereFuzzy('name', 'jd') ->withMinimumRelevance(70) ->first();
当使用 orWhereFuzzy
时,包括最小相关性作为可选的第三个参数
// Returns results which exceed 70 on the name column or 90 on the email column User::whereFuzzy(function ($query) { $query->orWhereFuzzy('name', 'jd', 70); $query->orWhereFuzzy('email', 'gm', 90); })->get();
性能(大型数据集)
当在大型表中搜索以仅确认是否存在匹配项时,删除排序和相关性检查将显著提高查询性能。为此,只需为 whereFuzzy
或 orWhereFuzzy
方法提供 false
作为第三个参数即可
DB::table('users') ->whereFuzzy('name', 'jd', false) ->orWhereFuzzy('name', 'gm', 0, false); ->first();
要调整相关性阈值,如果需要,您可以手动过滤相关性数据。
您还可以通过选择性地禁用一个或多个模式匹配器来进一步提高性能。只需提供要禁用的模式匹配器的 array
即可,例如。
DB::table('users') ->whereFuzzy('name', 'jd', true, [ 'AcronymMatcher', 'StudlyCaseMatcher', ]); ->first();
以下模式匹配器可以包含在 array
中
- ExactMatcher
- StartOfStringMatcher
- AcronymMatcher
- 连续字符Matcher
- 单词开头Matcher
- StudlyCaseMatcher
- 字符串中Matcher
- 字符串中出现的次数Matcher
查看/src/Matchers
目录以了解每个Matcher对查询的处理方式。
限制
无法使用paginate
方法,因为Quest忽略了用于获取所需记录数量的Laravel的二级查询中的相关性字段。然而,您可以使用simplePaginate
方法而不会出现问题。在许多情况下,这仍然是一个更好的选项,尤其是在处理大型数据集时,因为paginate
方法在滚动大量页面时变得缓慢。
贡献
感谢您考虑对Quest做出贡献。您可以提交包含改进的PR,但如果它们本质上是重大的,请确保还包括测试或测试。
许可
MIT许可(MIT)。有关更多信息,请参阅许可文件。