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

v1.0 2024-06-25 20:28 UTC

This package is auto-updated.

Last update: 2024-09-25 21:07:02 UTC


README

此包允许在Laravel数据库和Eloquent查询中执行伪模糊搜索。由于其模式匹配方法,它仅支持MySQLMariaDB,尽管我欢迎任何使支持如Postgres数据库的PR。

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

安装

使用composer引入包

composer require cobraprojects/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之间的整数。

请注意,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
  • StartOfStringMatcher
  • AcronymMatcher
  • ConsecutiveCharactersMatcher
  • StartOfWordsMatcher
  • StudlyCaseMatcher
  • InStringMatcher
  • TimesInStringMatcher

请查看/src/Matchers目录,以了解每个匹配器对查询做了什么。

限制

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

贡献

感谢您考虑为Quest做出贡献。您可以提交包含改进的PR,但如果它们是实质性的,请确保还包括测试或测试用例。

许可证

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