caneara/quest

此包已被放弃且不再维护。没有建议的替代包。

为Laravel数据库查询提供伪模糊搜索的包。

v4.0.0 2023-09-21 07:24 UTC

This package is auto-updated.

Last update: 2024-04-21 08:41:21 UTC


README

此包可以在Laravel数据库和Eloquent查询中启用伪模糊搜索。由于其模式匹配方法,它仅支持MySQLMariaDB,但我欢迎任何PR以启用对Postgres等数据库的支持。

此库的大部分内容基于Tom Lingham现在已废弃的Laravel Searchy包的出色工作。如果您对模糊搜索的工作原理感兴趣,请查看该项目的README。

安装

使用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();

如果您正在搜索多个字段,您可以将一个array提供给orderByFuzzy方法

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之间的整数。

请注意,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();

性能(大型数据集)

当搜索大型表以仅确认是否存在匹配项时,移除排序和相关性检查将显着提高查询性能。为此,只需为whereFuzzyorWhereFuzzy方法提供第三个参数为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
  • 字符串开始匹配器
  • 缩写匹配器
  • 连续字符匹配器
  • 单词开始匹配器
  • 大驼峰式匹配器
  • 字符串内匹配器
  • 字符串中出现次数匹配器

查看 /src/Matchers 目录,了解每个匹配器对查询的作用。

限制

无法使用带有 Quest 的 paginate 方法,因为在 Laravel 运行的二次查询中省略了相关性字段,以获取 LengthAwarePaginator 所需的记录数。然而,您可以使用 simplePaginate 方法而不会出现问题。在许多情况下,这仍然是一个更好的选择,尤其是在处理大量数据集时,因为当滚动大量页面时,paginate 方法会变得很慢。

贡献

感谢您考虑为 Quest 贡献。欢迎您提交包含改进的 PR,但如果它们本质上是重大的,请确保还包括测试或测试用例。

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件