php调用sphinx有两种方式,一是引入sphinx的接口,二是安装php的sphinx扩展。
首先我们来看下接口的方式
安装完sphinx后,在源码目录里有一个api,cd到api,ls下
我们可以看到有java,python,php和ruby的测试文件
学习阶段的话我们可以直接用sphinxapi.php来进行学习和测试。真正项目里应用一般各大php框架里都有相应封装好的扩展。直接composer的方式去安装使用就好了。
下面主要还是一起学习下sphinxapi里几个重要的方法。
1.sphinx重要的几个方法
①setMatchMode ( int $mode
)全文检索模式匹配
$mode表示匹配模式, 有以下5种匹配模式
Constant Description
SPH_MATCH_ALL 匹配所有查询关键字,比如你搜索"杭州钢材",那么实际搜索的是同时包含"杭州"和"钢材"两个关键字的文章
SPH_MATCH_ANY 匹配任意一个查询关键字,比如你搜索"杭州钢材",那么实际搜索的是包含"杭州"或"钢材"关键字的文章
SPH_MATCH_PHRASE 将查询看成一个词组,要求按顺序完整匹配,这个类似于select * like "%杭州钢材%"。比如你搜"2016年8月份杭州钢材"能搜到,但是搜2016年8月份杭州统计汇总,钢材价格"就搜不到。
SPH_MATCH_BOOLEAN 将查询看成一个布尔表达式,可以简单地进行与或运算。例如(杭州!钢材),搜索匹配杭州但是不匹配钢材的记录
SPH_MATCH_EXTENDED2 sphinx扩展匹配模式,将查询看成sphinx内部的表达式,可以使用以下运算符:
或 例如:杭州 |钢材
非 例如:杭州 !钢材
字段搜索符 例如@title 杭州 @description 钢材 表示搜索文章title包含杭州,描述包含钢材的记录<
字段限位 例如@title[100] 杭州 表示搜索标题包含杭州,并且标题长度不超过100的记录
多字段搜索符 例如@(title,content)杭州钢材 表示搜索标题或文章内容里包含"杭州钢材"的记录
严格搜索符 例如 杭州 << 钢材 表示杭州,钢材需要按顺序出现
字段开始和结束符 例如 ^杭州...钢材$ 表示限定必须以杭州开始,钢材结束
SPH_MATCH_FULLSCAN 完整扫描,此模式下所有的查询词都将被忽略,没有分词结果。
SPH_MATCH_EXTENDED 同SPH_MATCH_EXTEND2
②setSortMode 全文检索排序模式
Constant Description
SPH_SORT_RELEVANCE 按相关度评分排序,最好的匹配排在前面
SPH_SORT_ATTR_DESC 按照属性降序排列 例如 :setSortMode(SphinxClient::SPH_SORT_ATTR_DESC,'publish_time')按照发布时间降序
SPH_SORT_ATTR_ASC 按照属性升序排列 例如:setSortMode(SphinxClient::SPH_SORT_ATTR_ASC'publish_time')按照发布时间升序
SPH_SORT_TIME_SEGMENTS segments表示部分,段的意思。这个模式表示先按时间排序,再按相关度排序。这个时间是sphinx自己内部定义的规则
SPH_SORT_EXTENDED 按类似sql的方式排列组合起来,比如@weight desc,publish_time desc。表示先按权值,即匹配度降序,再按发布时间降序
其中以@开头的是内置属性,包括
@weight 权值
@id 文档id
@relevance 等同于weight
SPH_SORT_EXPR 表达式排序方式,即可以按照表达式计算出来的结果进行排序。例如 setSortMode(SphinxClient::SPH_SORT_EXPR,'@weight+@id')
③setRankingMode 搜索排名
Constant Description
SPH_RANK_PROXIMITY_BM25 Default ranking mode which uses both proximity and BM25 ranking
SPH_RANK_BM25 Statistical ranking mode which uses BM25 ranking only (similar to most of other full-text engines). This mode is faster, but may result in worse quality on queries which contain more than 1 keyword.
SPH_RANK_NONE 不进行排序
④setFilterRanging($attribute,$min,$max,$exclude=false)
指定一个值的范围,例如setFilterRanging('publish_time','2016-08-26 00:00:00','2016-08-27 00:00:00');第四个参数若为true,表示取不在这个范围的数据。
⑤setFieldweights(array $weights)设置查询的权重,权重大的会优先搜索
例如:
setFieldweights([
'title'=>10,
'content'=>6,
'description'=>3
]);//优先匹配title里包含关键字的,然后是content,然后是description。
⑥setLimits($offset,$limit,$max=1000,$cutoff)分页查询
$offset,$limit类似于mysql里的offset,limit.
$max表示搜索请求中返回的最大数据量,默认是1000.比如搜索"行情",实际上有10000条记录,但是没有设置此参数,默认只返回1000条记录。所有totals为1000.所以一般这个值须要设置。
$cutoff控制查询的数量限制,它跟$max的区别是:$max是返回的最大数据量,比如说实际搜到了10000条记录,但是只返回1000条。$cutoff表示一开始搜索时就限制搜索的数据量,比如最多搜索50条停止,那么搜索到50条就会停止搜索。这个一般可以不做设置。
⑦setGroupBy($attribute,$func,$groupsort='@group desc ')分组查询
$func默认有以下几个:
SPH_GROUPBY_DAY,
SPH_GROUPBY_WEEK,
SPH_GROUPBY_MONTH,
SPH_GROUPBY_YEAR,
SPH_GROUPBY_ATTR,
SPH_GROUPBY_ATTRPAIR
DAY,WEEK,MONTH,YEAR这个一般可以用于搜索最近一天,一周,一月或一年的记录。ATTR表示按照指定的属性值分组
⑧setArrayResult设置返回的数据为数组
⑨setFilter($attribute,array $value,$exclude = false)
属性过滤,例如setFilter('id',[1,2,3]);第三个参数若为true,表示id不为1,2,3的。
10.query($query,$index='*',$comment='')执行查询
第一个参数可以直接是一个关键字,也可以是查询的一个表达式。第二个参数表示查询的哪个索引。这个跟你sphinx.conf里的配置有关。$comment表示注释
以上只是主要的几个方法,还有其他的方法这里不再做阐述。php的各大框架一般都有相应的sphinx扩展,我们使用的是laravel框架,所以这里推荐laravel的sphinx扩展。
https://packagist.org/packages/wneuteboom/sphinxsearch
当然了lumen框架里做下修改也是可以用的。
php里调用sphinx例子:
php里如何调用呢,这里我给出在lumen框架里调用sphinx扩展的部分代码:
$result = $this->sphinx->search($keyword, $this->indexName)
->setMatchMode(SphinxClient::SPH_MATCH_EXTENDED2)
->setSortMode(SphinxClient::SPH_SORT_EXTENDED, '@weight desc,inputtime desc')
->setRankingMode(SphinxClient::SPH_RANK_PROXIMITY_BM25)
->range('inputtime', $startTime, $endTime)
->setFieldWeights([
'title' => 10,
'content' => 8,
'description' => 2
])
->limit($limit, $offset, 100000, 0)
->query();
if (false === $result) {//说明sphinx服务器没有启动
return $result;
}
$news = [];
if (!empty($result['matches'])) {
$opts = [
"before_match" => "<span style='color:red;'>",
"after_match" => "</span>",
"chunk_separator" => " ... ",
"limit" => 200,
"around" => 3,
];
foreach ($result['matches'] as $match) {
$item = [
'id' => $match['id'],
'title' => $this->sphinx->excerpt(strip_tags($match['attrs']['title']), $opts)[0],
'description' => $this->sphinx->excerpt(strip_tags($match['attrs']['content']), $opts)[0],
'inputtime' => date('Y-m-d', $match['attrs']['inputtime'])
];
$news[] = (object)$item;
}
}