ripaclub / sphinxsearch
Sphinx Search 库提供了 SphinxQL 索引和搜索功能
Requires
- php: ^5.5 || ^7.0
- container-interop/container-interop: ~1.0
- zendframework/zend-db: ^2.4 || ^3.0
- zendframework/zend-servicemanager: ^2.4 || ^3.0
Requires (Dev)
- phpunit/phpunit: ~4.3
- satooshi/php-coveralls: dev-master
Suggests
- ripaclub/zf2-sphinxsearch: ZF2 integration module for SphinxSearch library
- ripaclub/zf2-sphinxsearch-tool: Utility that provides a set of tools to create and handle Sphinx Search configs and sources
README
Sphinx Search 库提供了 SphinxQL 索引和搜索功能。
简介
本库旨在提供
- 基于 Zend\Db\Sql 的 SphinxQL 查询构建器
- 一个简单的 搜索 类
- 用于处理 RT 索引的 索引器 类
- 通过 Zend\Db\Adapter 的 SphinxQL 连接工厂
我们还准备了一套相关的 实用工具。您可以使用它们与此库配合使用。
-
ripaclub/zf2-sphinxsearch-tool
一组用于创建和自动化 SphinxSearch 配置文件的 工具
-
一个模块,用于快速启动和集成 SphinxSearch 库与 Zend Framework
-
一个用于快速启动和集成 SphinxSearch 库与 Symfony 的包
-
SphinxSearch docker 镜像(适用于各种 SphinxSearch 版本和测试版)
注意
由于通过 Sphinx API 可用的所有内容也通过 SphinxQL 可用,但反之则不然(即,写入 RT 索引只能通过 SphinxQL 进行),因此本库不使用 SphinxClient
PHP 扩展。
安装
使用 composer
将以下内容添加到您的 composer.json
文件中
"require": { "ripaclub/sphinxsearch": "~0.8.0", }
注意
从版本 0.8.1 开始,完全支持 PHP 7 和 Zend Framework 3.x 系列的组件。
从 0.8.x 系列开始,最低要求是 PHP >= 5.5 和 Zend Framework 依赖项 >= 2.4。
如果您必须使用小于(或等于)5.4 的 PHP 版本和/或小于(或等于)2.3 的 Zend Framework 依赖项,则可以使用 0.7.1 版本。
配置(简单)
要使用库组件,您需要一个适配器实例。您可以使用内置工厂简单地获取配置适配器,如下面的示例所示
use Zend\ServiceManager\ServiceManager; use Zend\ServiceManager\Config; $serviceManagerConfig = new Config([ 'factories' => [ 'SphinxSearch\Db\Adapter\Adapter' => 'SphinxSearch\Db\Adapter\AdapterServiceFactory' ], 'aliases' => [ 'sphinxql' => 'SphinxSearch\Db\Adapter\Adapter' ] ]); $serviceManager = new ServiceManager(); $serviceManagerConfig->configureServiceManager($serviceManager); $serviceManager->setService('Config', [ 'sphinxql' => [ 'driver' => 'pdo_mysql', 'hostname' => '127.0.0.1', 'port' => 9306, 'charset' => 'UTF8' ] ]); $adapter = $serviceManager->get('sphinxql');
注意
仅支持两种驱动程序
pdo_mysql
mysqli
有关更多详细信息,请参阅 适配器服务工厂 部分。
用法
搜索
假设 $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(['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)
其他实用方法如 setSpecifications
、getRawState
和 reset
均完全支持。
相反,quantifier
、join
和 combine
只是忽略,因为 SphinxQL 语法中没有它们。
索引器
假设 $adapter
已经通过 ServiceManager
获取,我们可以在索引上执行文档索引操作,前提是我们操作的是 实时 索引。
use SphinxSearch\Indexer; $indexer = new Indexer($adapter); $indexer->insert( 'foo', [ '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
实例允许从实时索引中更新和删除行(分别使用 update
和 delete
方法)。
高级
适配器服务工厂
这个库包含两个工厂,以便正确配置 Zend\Db\Adapter\Adapter
以与 Sphinx Search 一起工作。
使用 SphinxSearch\Db\Adapter\AdapterServiceFactory
(见上面的 配置 部分),对于单个连接;如果需要使用多个连接,请使用提供的 SphinxSearch\Db\Adapter\AdapterAbstractServiceFactory
,并在 ServiceManager
中注册,如下所示
'service_manager' => [ 'abstract_factories' => [ 'SphinxSearch\Db\Adapter\AdapterAbstractServiceFactory' ], ]
有关抽象工厂配置,请参阅 Zend Db Adpater Abstract Factory 文档。
预处理语句
SphinxQL 不支持预处理语句,但 PDO 驱动器能够模拟客户端预处理语句。为了达到预处理查询的好处,这个库完全支持这个功能。
注意
PDO 驱动器支持预处理和非预处理查询。Mysqli
驱动器不支持预处理查询。
对于 SphinxSearch\Search
和 SphinxSearch\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
的值,驱动器将抛出异常。 -
boolean
SphinxQL 没有原生布尔类型,但如果您尝试使用 PHP
bool
,库和驱动器将分别将值转换为0
或1
。 -
integer
当 SphinxQL 预期
uint
时,PHP 原生整数可以正常工作。请注意,包含整数的字符串在过滤器中不起作用(即WHERE
子句)。
警告:PHP 整数是带符号的,而 SphinxQL 仅支持无符号整数和 UNIX 时间戳。 -
float
由于与
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'
)才会工作。
- 实际上,Sphinx SQL 解释器将不带小数部分的数字视为整数。因此,假设
因此,我们建议在构建查询时始终使用合适的 PHP 原生类型(即,不要使用字符串表示数值字段)。
有用链接:[Sphinx 属性文档](http://sphinxsearch.com/docs/current.html#attributes)。
SQL 对象
正如 Zend\Db\Sql,这个库提供了一系列 SQL 对象。
SphinxSearch\Db\Sql\Select
在 搜索 段落中解释。SphinxSearch\Db\Sql\Insert
SphinxSearch\Db\Sql\Replace
与插入相同,但会覆盖重复的 IDSphinxSearch\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(['bigattr' => 1000, 'fattr' => 3465.23]) ->where(new Match('?', 'hehe')) ->where(['enabled' => 1]) ->option('strict', 1);
然后您可以通过以下方式执行查询
$statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute();
或者使用 Search
或 Indexer
组件
$resultset = $indexer->updateWith($update);
因此,每个对象(具有 where()
方法)都支持 Match
表达式,如下一段所述。
查询表达式
SphinxSearch\Query\QueryExpression
类提供了一种占位符表达式方式和字符串转义机制,以便安全地使用 Sphinx 查询语法。此外,组件设计允许它独立使用,因为它不依赖于其他库组件。
一些示例
use SphinxSearch\Query\QueryExpression; $query = new QueryExpression('@title ? @body ?', ['hello', 'world']); echo $query->toString(); //outputs: @title hello @body world echo $query->setExpression('"?"/3') ->setParameters(['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(['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/? "?"', ['hello', 3, 'world', 4, '"my test"'])) ->where(['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 --exclude-group=integration
要运行集成测试,请执行
./vendor/bin/phpunit
注意
要执行集成测试,您需要一个运行中的 SphinxSearch 实例(例如,使用正确配置的 docker 映像)。