loilo/fuse

基于 Bitap 算法的 PHP 模糊搜索

维护者

详细信息

github.com/Loilo/Fuse

源代码

问题

安装次数: 939 123

依赖项: 13

建议者: 0

安全: 0

星星: 323

观察者: 11

分支: 30

7.0.1 2023-11-27 17:21 UTC

README

The Fuse logo, a violet asterisk, in reference to the Fuse.js logo

Fuse

PHP 的模糊搜索库

Tests Packagist PHP Version

这是一个优秀项目 Fuse.js 的 PHP 版本,并尽可能提供完整的 API 兼容性。

查看他们的 演示示例,以了解这个库的能力。

最新兼容的 Fuse.js 版本:7.0.0

目录

安装

此包可通过 Composer 获取。要将它添加到您的项目中,只需运行

composer require loilo/fuse

注意,使用 Fuse 至少需要 PHP 7.4。

使用

以下是一个简单的使用示例

<?php
require_once 'vendor/autoload.php';

$list = [
    [
        'title' => "Old Man's War",
        'author' => 'John Scalzi',
    ],
    [
        'title' => 'The Lock Artist',
        'author' => 'Steve Hamilton',
    ],
    [
        'title' => 'HTML5',
        'author' => 'Remy Sharp',
    ],
    [
        'title' => 'Right Ho Jeeves',
        'author' => 'P.D Woodhouse',
    ],
];

$options = [
    'keys' => ['title', 'author'],
];

$fuse = new \Fuse\Fuse($list, $options);

$fuse->search('hamil');

这将导致以下结果(其中每个结果中的 item 指的是匹配的条目本身,而 refIndex 提供了项目在原始 $list 中的位置)

[
    [
        'item' => [
            'title' => 'The Lock Artist',
            'author' => 'Steve Hamilton',
        ],
        'refIndex' => 1,
    ],
    [
        'item' => [
            'title' => 'HTML5',
            'author' => 'Remy Sharp',
        ],
        'refIndex' => 2,
    ],
];

选项

Fuse 有很多选项可以细化您的搜索

基本选项

isCaseSensitive

  • 类型: bool
  • 默认: false

表示比较是否应该区分大小写。

includeScore

  • 类型: bool
  • 默认: false

是否应在结果集中包含分数。分数为 0 表示完美匹配,分数为 1 表示完全不匹配。

includeMatches

  • 类型: bool
  • 默认: false

是否应在结果集中包含匹配项。当 true 时,结果集中的每条记录将包括匹配字符的索引。这些可以相应地用于突出显示目的。

minMatchCharLength

  • 类型: int
  • 默认: 1

只有长度超过此值的匹配才会被返回。(例如,如果您想忽略结果中的单字符匹配,将其设置为 2)。

shouldSort

  • 类型: bool
  • 默认: true

是否按分数排序结果列表。

findAllMatches

  • 类型: bool
  • 默认: false

当为 true 时,即使字符串中已经找到完美匹配,匹配函数也会继续到搜索模式的末尾。

keys

  • 类型: array
  • 默认: []

要搜索的键的列表。这支持嵌套路径、加权搜索、在 字符串对象 数组中进行搜索。

模糊匹配选项

location

  • 类型: int
  • 默认: 0

确定模式预期在文本中的位置。

threshold

  • 类型: float
  • 默认: 0.6

匹配算法何时放弃。阈值为 0.0 需要完美匹配(包括字母和位置),阈值为 1.0 将匹配任何内容。

distance

  • 类型: int
  • 默认: 100

确定匹配必须接近于模糊位置(由 location 指定)。如果字母匹配与模糊位置相距 distance 个字符,则计分为完全不匹配。如果 distance0,则匹配必须位于指定的 location。如果 distance1000,则要求完美匹配必须位于 location800 个字符内,以使用 threshold0.8

ignoreLocation

  • 类型: bool
  • 默认: false

true 时,搜索将忽略 locationdistance,因此字符串中模式出现的任何位置都不会影响。

提示: 默认选项仅搜索前60个字符。如果合理地预计匹配在范围内,则这应该足够。要修改此行为,设置合适的 locationthresholddistance(或 ignoreLocation)组合。

为了更好地理解这些选项如何协同工作,请阅读有关 Fuse.js评分理论 的内容。

高级选项

useExtendedSearch

  • 类型: bool
  • 默认: false

true 时,它启用使用类似Unix的搜索命令。请参阅 示例

getFn

  • 类型: callable
  • 默认:

用于检索对象在提供的路径上值的函数。默认还将搜索嵌套路径。

sortFn

  • 类型: callable
  • 默认:

用于对所有结果进行排序的函数。默认按相关性分数升序、索引升序排序。

ignoreFieldNorm

  • 类型: bool
  • 默认: false

true 时,用于相关性分数(用于排序)的计算将忽略 字段长度范数

提示: 只有在字段的数量不重要,但查询项存在时,才应该将 ignoreFieldNorm 设置为 true

fieldNormWeight

  • 类型: float
  • 默认: 1

确定字段长度范数对评分的影响程度。值为 0 等同于忽略字段长度范数。值为 0.5 将大大减少字段长度范数的影响,而值为 2.0 将大大增加其影响。

全局配置

您可以通过 config 方法访问和操作所有上述选项的默认值。

// Get an associative array of all options listed above
Fuse::config();

// Merge associative array of options into default config
Fuse::config(['shouldSort' => false]);

// Get single default option
Fuse::config('shouldSort');

// Set single default option
Fuse::config('shouldSort', false);

方法

以下方法在每个 Fuse\Fuse 实例上可用

search

搜索整个文档集合,并返回搜索结果列表。

public function search(mixed $pattern, ?array $options): array

参数 $pattern 可以是以下之一

参数 $options

  • limit(类型: int):表示返回的搜索结果的最大数量。

setCollection

设置/替换整个文档集合。如果没有提供索引,将生成一个。

public function setCollection(array $docs, ?\Fuse\Core\FuseIndex $index): void

示例

$fruits = ['apple', 'orange'];
$fuse = new Fuse($fruits);

$fuse->setCollection(['banana', 'pear']);

add

向集合添加文档并相应地更新索引。

public function add(mixed $doc): void

示例

$fruits = ['apple', 'orange'];
$fuse = new Fuse($fruits);

$fuse->add('banana');

sizeof($fruits); // => 3

remove

移除所有由谓词返回真值的文档,并返回被移除的文档数组。谓词使用两个参数调用: ($doc, $index)

public function remove(?callable $predicate): array

示例

$fruits = ['apple', 'orange', 'banana', 'pear'];
$fuse = new Fuse($fruits);

$results = $fuse->remove(fn($doc) => $doc === 'banana' || $doc === 'pear');
sizeof($fuse->getCollection()); // => 2
$results; // => ['banana', 'pear']

removeAt

移除指定索引处的文档。

public function removeAt(int $index): void

示例

$fruits = ['apple', 'orange', 'banana', 'pear'];
$fuse = new Fuse($fruits);

$fuse->removeAt(1);

$fuse->getCollection(); // => ['apple', 'banana', 'pear']

getIndex

返回生成的Fuse索引。

public function getIndex(): \Fuse\Core\FuseIndex

示例

$fruits = ['apple', 'orange', 'banana', 'pear'];
$fuse = new Fuse($fruits);

$fuse->getIndex()->size(); // => 4

索引

以下方法在每个 Fuse\Fuse 实例上可用

Fuse::createIndex

从列表预先生成索引并将其直接传递到Fuse实例。如果列表(相当)大,则可以提高实例化速度。

public static function createIndex(array $keys, array $docs, array $options = []): \Fuse\Core\FuseIndex

示例

$list = [ ... ]; // See the example from the 'Usage' section
$options = [ 'keys' => [ 'title', 'author.firstName' ] ];

// Create the Fuse index
$myIndex = Fuse::createIndex($options['keys'], $list);

// Initialize Fuse with the index
$fuse = new Fuse($list, $options, $myIndex);

Fuse::parseIndex

解析JSON序列化的Fuse索引。

public static function parseIndex(array $data, array $options = []): \Fuse\Core\FuseIndex

示例

// (1) When the data is collected

$list = [ ... ]; // See the example from the 'Usage' section
$options = [ 'keys' => [ 'title', 'author.firstName' ] ];

// Create the Fuse index
$myIndex = Fuse::createIndex($options['keys'], $list);

// Serialize and save it
file_put_contents('fuse-index.json', json_encode($myIndex));


// (2) When the search is needed

// Load and deserialize index to an array
$fuseIndex = json_decode(file_get_contents('fuse-index.json'), true);
$myIndex = Fuse::parseIndex($fuseIndex);

// Initialize Fuse with the index
$fuse = new Fuse($list, $options, $myIndex);

与 Fuse.js 的区别

开发

项目范围

请注意,我正在努力与Fuse.js保持功能一致性,因此不会添加Fuse.js本身未反映的搜索逻辑功能或修复。

如果您在使用这个PHP端口搜索结果时遇到的问题不是显然的bug,并且您恰好了解JavaScript,请检查您的用例是否在Fuse.js在线演示中正确运行,因为那是规范化的Fuse实现。如果问题同样出现在那里,请在他们的仓库中提交一个问题。

设置

要开始开发Fuse,您需要git、PHP(≥ 7.4)和Composer。

由于代码使用Prettier格式化,因此也建议安装Node.js/npm以及使用支持Prettier格式化的编辑器

克隆仓库并进入

git clone https://github.com/loilo/fuse.git
cd fuse

安装Composer依赖项

composer install

安装npm依赖项(可选但推荐)。这仅用于代码格式化,因为npm依赖项包括本项目使用的Prettier插件。

npm ci

质量保证

本项目有不同种类的代码检查。所有这些检查在提交拉取请求时都会运行,也可以在本地运行。

贡献

在提交拉取请求之前,请向test文件夹添加相关测试。