etrepat / compleet
基于Redis的快速自动补全服务
Requires
- php: >=5.4.0
- predis/predis: >=0.8.0
Requires (Dev)
- phpunit/phpunit: ~4.0
This package is auto-updated.
Last update: 2024-09-23 03:40:13 UTC
README
Compleet 是由 Eric Waller 编写的出色的 Soulmate ruby gem 的 PHP 版本,所有功劳都应该归功于原始库的作者。
此库可以帮助您解决开发快速自动补全功能的常见问题。它使用 Redis 的有序集合构建部分完成单词及其对应顶级匹配项的索引,并提供简单的接口来查询它们。Compleet 可完成您的句子。
Compleet 需要 PHP >= 5.4(或 HHVM >= 3.2)以及其唯一依赖项是 Composer 本身和出色的 Redis PHP 客户端库 Predis。
入门
Compleet 以 composer 包的形式发布,因此请将其添加到您的 composer.json
文件中作为需求
{ "require": { "etrepat/compleet": "~1.0" } }
然后通过运行 composer update
或 composer install
更新您的包。
用法
Compleet 设计得简单快捷,其主要功能包括
- 在单个查询中为多种类型的项提供建议。
- 按用户指定的分数排序结果,否则按词典顺序排序。
- 为每个项存储任意元数据。您可以存储url、缩略图路径等。
项 是一个简单的 JSON 对象,看起来像
{ "id": 3, "term": "Citi Field", "score": 81, "data": { "url": "/citi-field-tickets/", "subtitle": "Flushing, NY" } }
其中 id
是唯一标识符(在特定类型内),term
是您希望提供补全的短语,score
是用户指定的排名指标(对于具有相同分数的项,redis 将按词典顺序排序),data
是可选的容器,用于在匹配此项时返回元数据。
管理项
在能够执行任何自动补全搜索之前,我们首先必须将一些数据加载到我们的 Redis 数据库中。为了将数据加载到 Redis 服务器实例中进行后续查询,Compleet 提供了 Loader
类
require __DIR__ . '/vendor/autoload.php'; $loader = new Compleet\Loader('venues');
构造函数参数是我们将要添加/删除或加载的项的类型。我们稍后会将此相同的类型用于搜索。这是为了我们可以添加几种完全区分的数据类型,并将其分别索引到 Redis 中。
默认情况下,Compleet\Loader
对象会在需要时立即实例化到本地 Redis 实例。如果您想改变这种行为,您可以在构造函数中提供一个连接
require __DIR__ . '/vendor/autoload.php'; $redis = new Predis\Client('tcp://127.0.0.1/6379?database=0'); $loader = new Compleet\Loader('venues', $redis);
或者使用 setConnection
方法
require __DIR__ . '/vendor/autoload.php'; $redis = new Predis\Client('tcp://127.0.0.1/6379?database=0'); $loader = new Compleet\Loader('venues'); $loader->setConnection($redis);
加载项
现在我们有了加载器对象,我们可能想用它将大量项加载到我们的 Redis 数据库中。假设我们有一个以下 PHP 项数组(它遵循前面的 JSON 结构)
$items = array( array( 'id' => 1, 'term' => 'Dodger Stadium', 'score' => 85, 'data' => array( 'url' => '/dodger-stadium/tickets', 'subtitle' => 'Los Angeles, CA' ) ), array( 'id' => 28, 'term' => 'Angel Stadium', 'score' => 85, 'data' => array( 'url' => '/angel-stadium- tickets/', 'subtitle' => 'Anaheim, CA' ) ) ... etc ... );
要将这些项加载到 Redis 以供后续查询并清除现有数据,我们有 load
方法
$loader->load($items);
添加项
我们可以用类似的方式使用 add
方法添加单个项
$item = array( 'id' => 30, 'term' => 'Chase Field', 'score' => 85, 'data' => array( 'url' => '/chase-field-ticket/', 'subtitle' => 'Phoenix, AZ' ) ); $loader->add($item);
add
方法单独追加项,而无需先清除索引。
对于load
和add
方法,每个项目都必须提供id
和term
数组键。所有其他属性都是可选的。
删除项目
同样,如果我们需要删除单个项目,remove
方法可以完成这个操作
$item = array( 'id' => 30, 'term' => 'Chase Field', 'score' => 85, 'data' => array( 'url' => '/chase-field-ticket/', 'subtitle' => 'Phoenix, AZ' ) ); $loader->remove($item);
仅使用id
键,实际上是必须的。
清除索引
要清除之前索引的所有数据,我们可以使用clear
方法
$loader->clear();
查询
类似于Compleet\Loader
类,Compleet提供了Matcher
类,它将允许我们对之前索引的数据进行查询。它的工作方式非常相似,并接受相同的构造函数参数
require __DIR__ . '/vendor/autoload.php'; $redis = new Predis\Client('tcp://127.0.0.1/6379?database=0'); $matcher = new Compleet\Matcher('venues', $redis); // or: // $matcher = new Compleet\Matcher('venues'); // $matcher->setConnection($redis);
同样,第一个构造函数参数是我们实际要查询的项目类型。
然后,matches
方法将允许我们对提供的术语对索引数据进行查询
$results = $matcher->matches('stad');
这将针对venues
类型的部分完成单词索引进行搜索,并将返回与术语stad
匹配的项目数组。结果数组将按提供的分数或无分数时按字母顺序排序。
matches
方法还支持将选项数组作为第二个参数传递
$queryOptions = array( // resultset size limit (defaults to 5) 'limit' => 5, // whether to cache the results or not (defaults to true) 'cache' => true // cache expiry time in seconds (defaults to 600) 'expiry' => 600 ); $results = $matcher->matches('stad', $queryOptions);
将limit
选项设置为0
将返回所有与提供的术语匹配的结果。
将单个术语与多个项目类型匹配应该很容易
$types = array('products', 'categories', 'brands'); $results = array(); foreach($types as $type) { $matcher = new Compleet\Matcher($type); $results[$type] = $matcher->matches('some term'); }
使用CLI
Compleet还提供了一个CLI工具,名为compleet
脚本,用于从JSON文档/文件中轻松索引数据。它也可以用于测试目的进行查询。像许多提供二进制的composer包一样,它可能会放在项目的vendor/bin
文件夹中。
要从CLI将数据加载到redis中,您可以将JSON文件中的项目管道到compleet load TYPE
命令。
以下是一个示例venues.json
(每行一个JSON项)
{"id":1,"term":"Dodger Stadium","score":85,"data":{"url":"\/dodger-stadium-tickets\/","subtitle":"Los Angeles, CA"}} {"id":28,"term":"Angel Stadium","score":85,"data":{"url":"\/angel-stadium-tickets\/","subtitle":"Anaheim, CA"}} {"id":30,"term":"Chase Field ","score":85,"data":{"url":"\/chase-field-tickets\/","subtitle":"Phoenix, AZ"}} {"id":29,"term":"Sun Life Stadium","score":84,"data":{"url":"\/sun-life-stadium-tickets\/","subtitle":"Miami, FL"}} {"id":2,"term":"Turner Field","score":83,"data":{"url":"\/turner-field-tickets\/","subtitle":"Atlanta, GA"}}
以下是加载命令(compleet
实用程序将假设redis在默认端口上本地运行,或者您可以使用--redis
参数指定redis连接字符串)
$ vendor/bin/compleet load venues < venues.json
运行compleet -h
将列出CLI支持的所有操作及其参数。所有可以通过编程执行的命令都可以从compleet
实用程序运行。
在您的框架中使用Compleet
Compleet是一个独立的composer包,并且应该可以在不使用PHP框架的情况下直接使用。实际上,不需要框架。
在Laravel中使用Compleet
在Laravel >= 4.2中提供了Laravel Compleet包,用于Compleet的集成。它可以帮助减少使项目中的自动完成功能有用的样板代码量,并添加了全局配置、artisan命令、redis连接重用、控制器代码、路由等几个很好的集成。
查看Laravel Compleet项目页面以获取有关如何在您的Laravel应用程序中使用Compleet的更多信息。
贡献
想要贡献吗?也许你发现了一些讨厌的bug?这是个好消息!
- 分支并克隆项目:
git clone git@github.com:your-username/compleet.git
。 - 运行测试并确保它们在您的设置中通过:
phpunit
。 - 创建您的bug修复/功能分支并编写您的更改。为您的更改添加测试。
- 确保所有测试仍然通过:
phpunit
。 - 将更改推送到您的分支并提交新的pull request。
许可证
Compleet根据MIT许可证的条款进行许可(有关详细信息,请参阅LICENSE文件)。
由Estanislau Trepat (etrepat)编写。我还在twitter上@etrepat。