joacub/sphinxsearch

Sphinx Search 库提供 SphinxQL 索引和搜索功能

0.7.0 2014-09-30 15:10 UTC

This package is not auto-updated.

Last update: 2024-09-22 06:22:11 UTC


README

Sphinx Search 库提供 SphinxQL 索引和搜索功能。

简介

本库旨在提供

  • 基于 Zend\Db\Sql 的 SphinxQL 查询构建器
  • 一个简单的 Search
  • 一个用于处理 RT 索引的 Indexer
  • 通过 Zend\Db\Adapter 的 SphinxQL 连接工厂
注意

本库不使用 SphinxClient PHP 扩展,因为通过 Sphinx API 可用的所有功能也都可通过 SphinxQL 使用,反之则不然(例如,写入 RT 索引只能通过 SphinxQL 进行)。

安装

使用 composer

将以下内容添加到您的 composer.json 文件中

"require": {
	"php": ">=5.3.3",
	"ripaclub/sphinxsearch": "~0.6",
}

或者使用 git 子模块

git submodule add https://github.com/ripaclub/sphinxsearch.git ripaclub/sphinxsearch

配置(简单)

通过 service_manager 配置节点注册提供的工厂

'service_manager' => array(
	'factories' => array(
  		'SphinxSearch\Db\Adapter\Adapter' => 'SphinxSearch\Db\Adapter\AdapterServiceFactory',
	),
	// Optionally
	'aliases' => array(
		'sphinxql' => 'SphinxSearch\Db\Adapter\Adapter'
	),
)

然后在您的配置中添加 sphinxql 节点,并使用示例中的连接参数进行配置

'sphinxql' => array(
	'driver'    => 'pdo_mysql',
	'hostname'  => '127.0.0.1',
	'port'      => 9306,
	'charset'   => 'UTF8'
)

更多详细信息请参阅“适配器服务工厂”部分。

用法

搜索

假设 $adapter 已通过 ServiceManager 获取

use SphinxSearch\Search;
use SphinxSearch\Db\Sql\Predicate\Match;

$search = new Search($adapter);
$rowset = $search->search('foo', new Match('?', 'ipsum dolor'));

echo 'Founds row:' . PHP_EOL;
foreach ($rowset as $row) {
	echo $row['id'] . PHP_EOL;
}

search() 方法接受索引名称(或索引数组)作为第一个参数,第二个参数接受一个 where 条件(与 Zend\Db\Sql\Select::where() 相同)。此外,search() 的第二个参数可以接受一个闭包,该闭包将传入正在使用的 Select 对象,该对象用于构建 SELECT 查询。

以下用法是可能的

use SphinxSearch\Search;
use SphinxSearch\Db\Sql\Select;
use SphinxSearch\Db\Sql\Predicate\Match;

$search = new Search($adapter);
$rowset = $search->search('foo', function(Select $select) {
	$select->where(new Match('?', 'ipsum dolor'))
	       ->where(array('c1 > ?' => 5))
               ->limit(1);
});

SphinxSearch\Db\Sql\Select 类(类似于我们从其扩展的 Zend\Db\Sql\Select)支持以下与 SQL 标准子句相关的方法

$select->from($table)
$select->columns(array $columns)
$select->where($predicate, $combination = Predicate\PredicateSet::OP_AND)
$select->group($group)
$select->having($predicate, $combination = Predicate\PredicateSet::OP_AND)
$select->order($order)
$select->limit($limit)
$select->offset($offset)
// And also variable overloading for:
$select->where
$select->having

因此,它添加了一些 SphinxQL 特定方法

$select->withinGroupOrder($withinGroupOrder)
$select->option(array $values, $flag = self::OPTIONS_MERGE)

其他实用方法,如 setSpecificationsgetRawStatereset,都得到了完全支持。

相反,quantifierjoincombine 只被忽略,因为 SphinxQL 语法中没有这些。

索引器

假设 $adapter 已通过 ServiceManager 获取,我们可以执行文档的索引,前提是我们所作用的索引是 实时

use SphinxSearch\Indexer;

$indexer = new Indexer($adapter);
$indexer->insert(
	'foo',
	array(
		'id' => 1,
		'short' => 'Lorem ipsum dolor sit amet',
		'text' => 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit ...'
	),
	true
);

注意 insert 方法的第三个参数是一个布尔标志,指示是否执行 "upsert" 而不是插入。

此外,Indexer 实例允许通过 updatedelete 方法更新和删除实时索引中的行(分别使用方法和方法)。

高级

适配器服务工厂

本库包含两个工厂,以便正确配置 Zend\Db\Adapter\Adapter 以与 Sphinx Search 一起工作。

使用 SphinxSearch\Db\Adapter\AdapterServiceFactory(参见上文中的配置部分),如果需要使用单个连接;如果需要使用多个连接,则使用随附的SphinxSearch\Db\Adapter\AdapterAbstractServiceFactory,如下注册到ServiceManager中:

'service_manager' => array(
	'abstract_factories' => array(
  		'SphinxSearch\Db\Adapter\AdapterAbstractServiceFactory'
	),
)

有关抽象工厂配置,请参阅Zend Db Adapter Abstract Factory文档

仅支持两个驱动程序:

  • PDO_MySQL
  • Mysqli

预处理语句

SphinxQL不支持预处理语句,但PDO驱动程序可以在客户端模拟预处理语句。为了实现预处理查询的优势,此库完全支持此功能。

注意

PDO驱动程序支持预处理和非预处理查询。Mysqli驱动程序不支持预处理查询。

对于SphinxSearch\SearchSphinxSearch\Indexer,您可以通过setQueryMode()方法选择工作模式,使用以下标志之一:

const QUERY_MODE_PREPARED   = 'prepared'; // use prepared statement
const QUERY_MODE_EXECUTE    = 'execute';  // do not use prepared statement
const QUERY_MODE_AUTO       = 'auto';     // auto detect best available option (prepared mode preferred)

使用auto选项时,组件将使用可用的最佳执行模式,如果驱动程序支持,则优先使用预处理模式。

处理类型

此库旨在在支持的驱动程序和模式之间标准化API使用,但由于SphinxQL的限制,有一些考虑因素:

  • NULL

    SphinxQL不支持NULL。库会透明地处理它以兼容SQL:如果尝试使用值为NULL,则驱动程序将抛出异常。

  • 布尔值

    SphinxQL没有原生的布尔类型,但如果尝试使用PHP的bool,库和驱动程序将分别将值转换为01

  • 整数

    当SphinxQL期望uint时,PHP的本地整数可以正常工作。请注意,包含整数的字符串在过滤器中不起作用(即WHERE子句)。
    警告:PHP整数是带符号的,而SphinxQL仅支持无符号整数和UNIX时间戳。

  • 浮点数

    由于与float值相关的SphinxQL特定问题(尤其是在WHERE子句中),默认情况下,它们被转换为与32位单精度兼容的字符串表示,然后作为文本包含在SQL查询中,即使在使用预处理语句的情况下也是如此。

    此功能仅在值是本地的PHP float时才起作用(无论如何,包含浮点数的字符串在Sphinx中不起作用)。如果需要,可以通过使用$adapter->getPlatform()->enableFloatConversion(false)全局禁用此行为。

    警告:禁用浮点数转换功能可能会产生意外的行为,一些值得注意的示例

    • 实际上,Sphinx SQL解释器将没有小数部分的数字视为整数。因此,假设f1为浮点列,如果尝试WHERE f1 = 10,则将得到42000 - 1064 - index foo: 不支持在浮点列上的'intvalues'过滤器类型,如果尝试WHERE f1 = 10.0,则将正常工作。
    • 由于SphinxQL不支持作为字符串引用的浮点数,而PDO驱动程序在预处理语句模式下无法绑定双精度(SQL浮点)参数,PDO驱动程序将简单地将其转换为字符串,产生一个与区域设置相关的转换(类似于PHP echo),因此它仅在LC_NUMERIC设置符合十进制表示法中的点作为分隔符时才会工作(例如,可以使用LC_NUMERIC='C'

因此,我们建议在构建查询时始终使用合适的PHP本地类型(即,不要使用字符串作为数字字段)。

有用的链接:Sphinx属性文档

SQL 对象

Zend\Db\Sql一样,此库提供了一组SQL对象:

  • SphinxSearch\Db\Sql\Select搜索段落中解释
  • SphinxSearch\Db\Sql\Insert
  • SphinxSearch\Db\Sql\Replace 与插入相同,但会覆盖重复的ID
  • SphinxSearch\Db\Sql\Update 具有处理 OPTION 子句的能力
  • SphinxSearch\Db\Sql\Delete
  • SphinxSearch\Db\Sql\Show

它们都可以通过 SphinxSearch\Db\Sql\Sql 类的方法获取

use SphinxSearch\Db\Sql\Sql;

$sql = new Sql($adapter);
$select = $sql->select();  	// @return SphinxSearch\Db\Sql\Select
$insert = $sql->insert();   // @return SphinxSearch\Db\Sql\Insert
$insert = $sql->replace();	// @return SphinxSearch\Db\Sql\Replace
$update = $sql->update(); 	// @return SphinxSearch\Db\Sql\Update
$delete = $sql->delete();  	// @return SphinxSearch\Db\Sql\Delete
$show   = $sql->show(); 	// @return SphinxSearch\Db\Sql\Show

或者可以直接实例化,如下面的示例所示

use SphinxSearch\Db\Sql\Update;
use SphinxSearch\Db\Sql\Predicate\Match;

$update = new Update;
$update->from('myindex')
       ->set(array('bigattr' => 1000, 'fattr' => 3465.23))
       ->where(new Match('?', 'hehe'))
       ->where(array('enabled' => 1))
       ->option('strict', 1);

然后您可以通过以下方式执行查询

$statement = $sql->prepareStatementForSqlObject($select);
$results = $statement->execute();

或者使用 SearchIndexer 组件

$resultset = $indexer->updateWith($update);

因此,每个对象(具有 where())都支持 Match 表达式,如下一节所述。

查询表达式

SphinxSearch\Query\QueryExpression 类提供了一种占位符表达式方式和字符串转义机制,以便安全地使用 Sphinx 查询语法。此外,组件设计允许它独立使用,因为它不依赖于其他库的组件。

一些示例

use SphinxSearch\Query\QueryExpression;

$query = new QueryExpression('@title ? @body ?', array('hello', 'world'));
echo $query->toString(); //outputs: @title hello @body world


echo $query->setExpression('"?"/3')
           ->setParameters(array('the world is a wonderful place, but sometimes people uses spe(ia| ch@rs'))
           ->toString(); //outputs: "the world is a wonderful place, but sometimes people uses spe\(ia\| ch\@rs"/3

echo $query->setExpression('? NEAR/? ? NEAR/? "?"')
           ->setParameters(array('hello', 3, 'world', 4, '"my test"'))
           ->toString(); //outputs: hello NEAR/3 world NEAR/4 "my test"

SphinxSearch\Db\Sql\Predicate\Match 类内部使用 QueryExpression,因此您可以直接在 SQL 查询中使用它

use SphinxSearch\Adapter\Platform\SphinxQL;
use SphinxSearch\Db\Sql\Select;
use SphinxSearch\Db\Sql\Predicate\Match;

$select = new Select;
$select->from('myindex')
       ->where(new Match('? NEAR/? ? NEAR/? "?"', array('hello', 3, 'world', 4, '"my test"')))
       ->where(array('enabled' => 1));

//outputs: SELECT * from `foo` WHERE MATCH('hello NEAR/3 world NEAR/4 "my test"') AND `enabled` = 1
echo $select->getSqlString(new SphinxQL());

测试

库源代码(在 master 分支上)100% 覆盖了单元测试。

通过 composer 安装开发依赖项后,您可以使用 phpunit 运行。

./vendor/bin/phpunit -c tests/

代码质量

运行 phpmd

./vendor/bin/phpmd library/ text phpmd.xml.dist

运行 phpcs

./vendor/bin/phpcs --standard=PSR2 library/

运行 pdepend

./vendor/bin/pdepend --exclude=tests,vendor --summary-xml=pdepend.log library/

Analytics