etrepat/compleet

基于Redis的快速自动补全服务

1.0.1 2014-10-15 15:39 UTC

This package is auto-updated.

Last update: 2024-09-23 03:40:13 UTC


README

Latest Stable Version Total Downloads License Build Status

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 updatecomposer 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 方法单独追加项,而无需先清除索引。

对于loadadd方法,每个项目都必须提供idterm数组键。所有其他属性都是可选的。

删除项目

同样,如果我们需要删除单个项目,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?这是个好消息!

  1. 分支并克隆项目:git clone git@github.com:your-username/compleet.git
  2. 运行测试并确保它们在您的设置中通过:phpunit
  3. 创建您的bug修复/功能分支并编写您的更改。为您的更改添加测试。
  4. 确保所有测试仍然通过:phpunit
  5. 将更改推送到您的分支并提交新的pull request。

许可证

Compleet根据MIT许可证的条款进行许可(有关详细信息,请参阅LICENSE文件)。

Estanislau Trepat (etrepat)编写。我还在twitter上@etrepat