<?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($fidis_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


*/