sphinx 1.10-实时索引 api

/*
* @todo : sphinx实时索引curd操作类,适应sphinx 1.10-beta版
* @created :Wed Nov 10 10:38:27 CST 2010
* @email:[email protected]
* @website:http://www.sphinxsearch.org
* @author blvming
* @version 1.0
* @example
*
* $sphinx = new SphinxRt('articleRt','127.0.0.1:9306');
*  //打开调试信息
* $sphinx->debug = true;
*  //查询
* $prodList = $sphinx->where($condition)->order($orderCondition)->group('prod_uid')->search();
* //插入数据
* $sphinxData['title'] = $title;
* $sphinxData['content'] = $content;
* $sphinx->insert($sphinxData);
*
*/

class SphinxRt
{
    private $_link; //sphinx 连接池
    protected $_field = array(); //当前索引的字段属性
    protected $_sql = array(); //sql表达式
    protected $queryStr = ''; //查询的sql

    public $rt = '' ; //當前索引
    public $error = ''; //最后的错误信息

    public $debug = false; //调试状态

    //构造函数
    public function __construct($rt='',$host='192.168.1.10:9306')
    {
        try {
            $this->_link = mysql_connect($host);
            if(!$this->_link)
            {
                throw  new Exception('sphinx 实时索引服务器连接失败!');
            }
            if($rt !='')
            {
                $this->rt = $this->_sql['rt'] = $rt;
            }
        }
        catch (Exception $e)
        {
            $this->error = $e->getMessage();
        }
    }

    /**
      +----------------------------------------------------------
      * @todo 设置索引表
      * @access public
      * @param param
      * @return void
      +----------------------------------------------------------
     */
    public  function rt($rt)
    {
        $this->_sql['rt'] = $this->rt = $rt;
        return $this;
    }

    /**
      +----------------------------------------------------------
      * @todo where 匹配条件.注意:这里一定要主动加上where 关键词 不能出现这样的情况 where 1
      * @access public
      * @param $where
      * @return void
      +----------------------------------------------------------
     */
    public  function where($where)
    {
        $this->_sql['where'] = ' where '.$where;
        return $this;
    }

    /**
         +----------------------------------------------------------
         * @todo limit
         * @access public
         * @param param
         * @return void
         +----------------------------------------------------------
        */
    public  function limit($limit)
    {
        $this->_sql['limit'] = $limit;
        return $this;
    }

    /**
            +----------------------------------------------------------
            * @todo option 评分权值设定等
            * @access public
            * @param param
            * @return void
            +----------------------------------------------------------
           */
    public  function option($option)
    {
        $this->_sql['option'] = $option;
        return $option;
    }
    /**
            +----------------------------------------------------------
            * @todo field
            * @access public
            * @param param
            * @return void
            +----------------------------------------------------------
           */
    public  function field($field)
    {
        $this->_sql['field'] = $field;
        return $this;
    }

    /**
               +----------------------------------------------------------
               * @todo order
               * @access public
               * @param param
               * @return void
               +----------------------------------------------------------
              */
    public  function order($order)
    {
        $this->_sql['order'] = $order;
        return $this;
    }
    /**
  +----------------------------------------------------------
  * @todo group
  * @access public
  * @param param
  * @return void
  +----------------------------------------------------------
 */
    public  function group($group,$withGroup)
    {
        $this->_sql['group'] = $group;
        if($group)
        {
            $this->_sql['withGroup'] = $withGroup;
        }
        return $this;
    }

    /**
      +----------------------------------------------------------
      * @todo 检索数据,并对数据进行排序,过滤,评分设定等
      * @access public
      * @param param
      * @example select * from rt where match('keyword') group by gid WITHIN GROUP ORDER BY @weight DESC
      *          order by gid desc limit 0,1 option ranker=bm25,max_matches=3,field_weights=(title=10,content=3);
      * @return array
      +----------------------------------------------------------
     */
    public  function search()
    {
        //排序
        if($this->_sql['order'] != '')
        {
            $orderSql = ' ORDER BY '.$this->_sql['order'];
        }
        //分组聚合
        if($this->_sql['group'] !='')
        {
            $groupSql = ' GROUP BY '.$this->_sql['group'];
            //组内排序
            if ($this->_sql['withGroup']!='') {
                $groupSql .= ' WITHIN GROUP ORDER BY '.$this->_sql['withGroup'];
            }
        }
        //附加选项
        if($this->_sql['option'] !='')
        {
            $optionSql = ' OPTION '.$this->_sql['option'];
        }
        //数量限制
        if($this->_sql['limit']!='')
        {
            $limitSql = 'limit '.$this->_sql['limit'];
        }
        //字段
        if($this->_sql['field']=='')
        {
            $field = '*';
        }
        else
        {
            $field= $this->_sql['field'];
        }

        if($this->_sql['where']!='')
        {
            $where = $this->_sql['where'];
        }
        else
        {
            $where ='';
        }

        $this->queryStr = sprintf("SELECT %s FROM %s %s %s %s %s %s",$field,$this->_sql['rt'],$where,$groupSql,$orderSql,$limitSql,$optionSql);

        $rs = $this->query();

        if($rs)
        {
            $resArr = array();
            while ($row = mysql_fetch_assoc($rs)) {
                $resArr[] = $row;
            }
            $resArr['meta'] = $this->getMeta();
            return $resArr;
        }
        return false;
    }

    /**
      +----------------------------------------------------------
      * @todo 添加索引,注意,这里的添加并未考虑并发操作,可能在sphinx端会出现id冲突
      * @access public
      * @param mixed $data  插入的数据
      * @return bool
      +----------------------------------------------------------
     */
    public  function insert($data,$lastId=0)
    {
        if(!empty($data))
        {
            if($lastId===0)
            {
                $lastId = $this->getLastId();
            }

            foreach ($data as $k=>$v) {
                $fields .= ','.$k;
                $values .= ",'".$v."'";
            }
            $this->queryStr = "insert into ".$this->_sql['rt']."(id".$fields.") values ($lastId {$values})";
            return $this->query();
        }
        $this->error = '插入数据不能为空';
        return false;
    }
    /**
      +----------------------------------------------------------
      * @todo 批量插入数据
      * @access public
      * @param mixed $datas
      * @param boolean $asStr 是否使用逗号分隔的方式一次性插入
      * @return void
      +----------------------------------------------------------
     */
    public  function insertAll($datas,$asStr=true)
    {
        if(!empty($datas))
        {
            $fields = 'id'; //字段
            $values ='';    //值
            $lastId = $this->getLastId();
            $i = 0;
            foreach ($datas as $k=>$v) {
                //一次性插入数据,格式化
                if($asStr)
                {
                    $values .=',('.($i+$lastId);
                    foreach ($v as $kk=>$va) {
                        //属性字段
                        if($i==0)
                        {
                            $fields .= ','.$kk;
                        }
                        $values .= ",'".$va."'";
                    }
                    $i++;
                    $values .= ')';
                }
                else
                {
                    $this->insert($v,$lastId);
                }
            }

            //批量数据sql格式化
            if($asStr)
            {
                $values = ltrim($values,',');
                $this->queryStr = sprintf("insert into {$this->_sql['rt']}(%s) values %s",$fields,$values);
                return $this->query();
            }

        }
        else
        {
            $this->error = '无效数据!';
            return false;
        }

    }

    /**
     +----------------------------------------------------------
     * @todo 更新索引数据
     * @access public
     * @param mixed $data 要更新的数据
     * @param int  $id  更新条件id
     * @return bool
     +----------------------------------------------------------
     */
    public  function update($data,$id,$insert=true)
    {
        if(!empty($data) || $id>0)
        {
            //如果未找到记录且不需要不需要插入的话
            if($insert ===false && $this->getById($id) ===false) return true;

            foreach ($data as $k=>$v) {
                $fields .= ','.$k;
                $values .= ",'".$v."'";
            }
            //若该条数据不存在,直接插入
            $this->queryStr = "replace into ".$this->_sql['rt']."(id".$fields.") values ($id{$values})";
            return $this->query();
        }
        $this->error = '无效更新数据!';
        return false;

    }

    /**
      +----------------------------------------------------------
      * @todo 条件删除索引,如,根据外部id删除
      * @access public
      * @param $condition
      * @return void
      +----------------------------------------------------------
     */
    public  function delBy($condition)
    {
        $rs = $this->where($condition)->search();

        if($rs)
        {
            foreach ($rs as $v) {
                if($v['id']) $idArr[] = $v['id'];
            }
            $this->delete($idArr);
            return true;
        }
        return false;
    }

    /**
    +----------------------------------------------------------
    * @todo 删除索引数据,sphinx暂未提供批量删除的功能,如 in (123,34,565);
    * @access public
    * @param mixed $id
    * @return void
    +----------------------------------------------------------
   */
    public  function delete($id)
    {
        if(is_array($id) && count($id)>=1)
        {
            $rs = true;
            foreach ($id as $v) {
                $this->queryStr = sprintf("delete from %s where id=%d",$this->_sql['rt'],$v);
                $rs &= $this->query();
            }
        }
        else
        {
            $this->queryStr = sprintf("delete from %s where id=%d",$this->_sql['rt'],$id);
            $rs =  $this->query();
        }

        return $rs;
    }
    /**
      +----------------------------------------------------------
      * @todo 清空表
      * @access public
      * @return bool
      +----------------------------------------------------------
     */
    public  function truncate()
    {
        $lastId = $this->getLastId();
        for ($i=1;$i<=$lastId;$i++)         {             $this->delete($i);
        }
        return true;
    }

    /**
      +----------------------------------------------------------
      * @todo 获取总记录
      * @access public
      * @param param
      * @return void
      +----------------------------------------------------------
     */
    public  function countAll()
    {
        $this->queryStr = "SELECT * FROM $this->_sql['rt'] ";
        $this->query();
        $meta = $this->getMeta();
        if($meta)
        {
            return  $meta['total_found'];
        }
        return false;
    }

    /**
      +----------------------------------------------------------
      * @todo 获取当前最大值id,实现如mysql的auto_increment功能
      * @access public
      * @param param
      * @return void
      +----------------------------------------------------------
     */
    public  function getLastId()
    {
        $this->queryStr = "select * from {$this->_sql['rt']} order by id desc limit 1";
        $rs = $this->query();

        //若存在值,则取最大id的值,否则为1
        $row = mysql_fetch_assoc($rs);
        if($row)
        {
            $lastId = $row['id']+1;
        }
        return $lastId?$lastId:1;

    }

    /**
         +----------------------------------------------------------
         * @todo 获取查询状态值
         * @access protected
         * @param param
         * @return array();
         +----------------------------------------------------------
        */
    protected  function getMeta()
    {
        $metaSql = "show meta";
        $meta = mysql_query($metaSql);
        while ($row = mysql_fetch_assoc($meta)) {
            $metaArr[$row['Variable_name']] = $row['Value'];
        }
        return $metaArr;
    }

    /**
      +----------------------------------------------------------
      * @todo 根据id获取记录
      * @access public
      * @param int $id
      * @return array
      +----------------------------------------------------------
     */
    public  function getById($id)
    {
        if($id>0)
        {
            $sql = "'select * from $this->rt where id=".$id;
            $rs = mysql_query($sql);
            $row = mysql_fetch_assoc($rs);
            return $row;
        }
        return false;
    }

    /**
      +----------------------------------------------------------
      * @todo 获取索引的字段值,前提条件是索引服务器中必须至少一个值,暂时没有api显示可以直接像mysql 的语句 desc table 来获取索引的字段;
      * @access public
      * @param param
      * @return void
      +----------------------------------------------------------
     */
    public  function _getField($rt)
    {
        $rt = $rt?$rt:$this->rt;
        $this->queryStr = "select * from {$rt} limit 1";
        $res = $this->query();
        if($res)
        {
            $row = mysql_fetch_assoc($res);
            $field = array_keys($row);
            unset($field[1]); //去掉weight,这个字段是sphinx的权重值
            return $field;
        }
        else
        {
            $this->error = '实时索引'.$rt.'没有任何记录,无法获取索引字段';
            return false;
        }
    }

    /**
      +----------------------------------------------------------
      * @todo mysql查询
      * @access public
      * @param param
      * @return void
      +----------------------------------------------------------
     */
    public  function query($sql = '')
    {
        if($sql == '')
        {
            $sql = $this->queryStr;
        }
        if(!$this->_link) $this->triggerDebug($this->debug);

        $rs = mysql_query($sql,$this->_link);
        if(!$rs) $this->error = mysql_error();
        $this->triggerDebug($this->debug);
        return $rs;
    }

    /**
      +----------------------------------------------------------
      * @todo 获取错误信息
      * @access public
      * @return string
      +----------------------------------------------------------
     */
    public  function getError()
    {
        return $this->error;
    }

    /**
         +----------------------------------------------------------
         * @todo 获取最后的sql语句
         * @access public
         * @param param
         * @return string
         +----------------------------------------------------------
        */
    public  function getLastSql()
    {
        return $this->queryStr;
    }

    /**
      +----------------------------------------------------------
      * @todo 触发错误信息
      * @access public
      * @param param
      * @return void
      +----------------------------------------------------------
     */
    public  function triggerDebug($debugMode=false)
    {
        if($debugMode)
        {
            $debugInfo = debug_backtrace();

            $errorStr = 'file:'.$debugInfo[0]['file'];
            $errorStr .= '
line:'.$debugInfo[0]['line'];
            $errorStr .= '
sql:'.$debugInfo[0]['object']->queryStr;
            $errorStr .= '
error:'.$debugInfo[0]['object']->error.'';

            if($debugInfo[0]['object']->error!='')die($errorStr);
            echo ($errorStr);
        }
        return ;
    }

}
?>

你可能感兴趣的:(sphinx 1.10-实时索引 api)