<?php
namespace imcat;
(!defined('RUN_INIT')) && die('No Init');
include DIR_STATIC.'/ximp/class/sphinxapi.cls_php';
// Sphinx搜索类
class extSphinx {
public $so = NULL;
public $cfgs = array();
public $idxs = array();
public $res = array();
public $opt = array();
public function __construct() {
$this->_init();
}
// $rs=$dop->getRecs() 通用mod全文搜索
function getRecs($mod='', $opt=array(), $filts=array()){
global $_cbase;
$groups = glbConfig::read('groups'); $mcfg = glbConfig::read($mod);
$sfid = basReq::val('sfid','','Key');
$sfkw = basReq::val('sfkw'); $keywd = basReq::val('keywd');
$sfkw = empty($sfkw) ? $keywd : $sfkw;
$qstr = empty($sfkw) ? '' : (empty($sfid) ? '' : "@$sfid ")."$sfkw";
$fields = array();
$stype = basReq::val('stype','','Key');
if($stype){
$mpid = $mcfg['pid'];
if(in_array($mpid,array('docs','advs'))){
$fields['catid'] = basSql::whrTree($mcfg['i'],'(crc32)',$stype);
}elseif(in_array($mpid,array('users','xxxxx'))){
$fields['grade'] = crc32($stype);
}elseif(in_array($mpid,array('coms','xxxxx'))){
//$fields['stype'] = $stype;
}
}
foreach ($groups as $key => $row) {
$kval = basReq::val($key,'','Key');
if(!empty($stype) && isset($mcfg['f'][$key])){
$kcfg = glbConfig::read($key);
$fields[$key] = basSql::whrTree($kcfg['i'],'(crc32)',$kval);
}
}
if(!empty($filts)) $fields = array_merge($fields,$filts);
$page = basReq::val('page',1,'N');
if(empty($opt['limit'])) $opt['limit'] = $_cbase['show']['apsize'];
if(empty($opt['offset'])) $opt['offset'] = ($page-1)*$opt['limit'];
if(empty($opt['ordby'])) $opt['ordby'] = '@id desc';
$this->opt = $opt;
$this->search($qstr, $mod, $fields, $opt);
$idstr = $this->idstr();
if(!empty($idstr)){
return glbDBObj::dbObj()->table(glbDBExt::getTable($mod))->where("spid IN($idstr)")->select();
}else{
return array();
}
}
// $dop->pgbar($idfirst,$idend);
public function pgbar($idfirst,$idend) {
$pg = new comPager('$sfrom','$where',$this->opt['limit'],'$order');
$pg->prec = $this->res['total'];
$pg->bar = $pg->links();
$pgs = $pg->show($idfirst,$idend);
if($idfirst=='rebar') return $pgs;
$op = "".basElm::setOption(basLang::show('flow.op_op3'),'',basLang::show('flow.op0_bacth'));
dopFunc::pageBar($pgs,$op);
}
// init
public function _init() {
//spcfgs
$spcfgs = glbConfig::read('sphinx','ex');
$this->cfgs = $spcfgs['cfgs'];
$this->idxs = $spcfgs['index'];
//初始化sphinx
$this->so = new \SphinxClient();
$this->so->SetServer($this->cfgs['host'], $this->cfgs['port']);
$this->so->SetConnectTimeout(3);
$this->so->SetArrayResult(true);
$this->so->SetMatchMode(SPH_MATCH_EXTENDED2); //匹配模式
$this->so->SetRankingMode(SPH_RANK_PROXIMITY_BM25); //仅使用BM25评分计算
//$res = $this->so->query('@title 人','index_imcat_demo_main,index_imcat_demo_delta');
//if(!empty($res['_error'])) die($res['_error']);
}
/**
* 搜索
* @param string $qstr 关键词 类似sql like'%$q%'
* @param string $spmod sp_model ex_sphinx.php里面设置
* @param array $fields 字段过滤 show=>1, show=>array(1), tagid=>array(1,2,3), atime=>array('min'=>123,'max'=>456)
* @param array $opt 选项 $offset=0, $limit=10, $ordby='@id desc'
*/
public function search($qstr, $spmod='', $fields=array(), $opt=array()) {
$spidx = empty($this->idxs[$spmod]) ? $spmod : $this->idxs[$spmod];
// 字段过滤
if(!empty($fields)) {
foreach($fields as $fid=>$arr){
if(is_array($arr) && isset($arr['min']) && isset($arr['max'])){
$this->so->SetFilterRange($fid, $arr['min'] , $arr['max'], false);
}else{
$this->so->SetFilter($fid, is_array($arr) ? $arr : array($arr));
}
}
}
// opt
$offset = isset($opt['offset']) ? $opt['offset'] : 0;
$limit = isset($opt['limit']) ? $opt['limit'] : 0;
$ordby = isset($opt['ordby']) ? $opt['ordby'] : '@id desc';
$limit = intval($limit);
if($limit) {
$this->so->SetLimits(intval($offset), $limit, ($limit>1200) ? $limit : 1200);
} //$qstr = "you";
if($ordby) { //排列
$this->so->SetSortMode(SPH_SORT_EXTENDED, $ordby);
}
// res
$this->res = $this->so->query($qstr, $spidx);
return $this->res;
}
public function idstr(){
if(empty($this->res['matches'])) return '0';
$ids = '';
foreach ($this->res['matches'] as $row) {
$ids .= (empty($ids) ? '' : ',')."{$row['id']}";
}
return $ids; // implode(',', array_keys($this->res['matches']));
}
}
/*
这里解释一下:
$sphinx->setFilter(‘tagid’, array(2,3,4));
是表示含有标签值2,3,4中的任意一个即符合筛选,这里是or关系。
$sphinx->setFilter(‘tagid’, array(2));
$sphinx->setFilter(‘tagid’, array(3));
$sphinx->setFilter(‘tagid’, array(4));
设置三个filter是标示,要同时满足2,3,4三个属性值才符合,这里是and关系。
// 设置扩展匹配模式 http://blog.csdn.net/u013699800/article/details/48316841
$sphinx->SetMatchMode ( "SPH_MATCH_EXTENDED2" );
//查询中使用条件语句,字段用@开头,搜索内容包含测试,toid等于1的邮件:
$result = $sphinx->query('@content (测试) & @toid =1', '*');
//用括号和&(与)、|、(或者)、-(非,即!=)设置更复杂的条件
$result = $sphinx->query('(@content (测试) & @subject =呃) | (@fromid -(100))', '*');
//更多语法请查看官方文档匹配模式的说明
https://www.cnblogs.com/redleaf1995/p/3831522.html
http://sphinxsearch.com/docs/current.html#extended-syntax
@title hello @body world
@(title,body) hello world
*/