1 <?php 2 namespace ServiceTools; 3 4 require_once(dirname(__FILE__)."/XunSearch/XS.php"); 5 class XunSearch 6 { 7 static $instace; 8 9 private $project; 10 private $index; 11 private $search; 12 private $tokenizer; 13 14 private $table_config=array( 15 "company"=>array( 16 "tablename"=>"k_company", 17 "use_field"=>"id,title", 18 "condition"=>"id=%d", 19 "primary_key"=>"id", 20 ), 21 22 ); 23 24 public static function getInstance($project=null) 25 { 26 return self::$instace ?: (self::$instace = new self($project)); 27 } 28 29 public function __construct($project) 30 { 31 $this->project=$project; 32 $this->setSearchConn($project); 33 } 34 35 public function setSearchConn($project) 36 { 37 if($project=="company"){ 38 $file_name=COMPANY_SEARCH_CONFIG; 39 } 40 $config_path=dirname(__FILE__)."/XunSearch/config/".$file_name; 41 if (!file_exists($config_path)){ 42 throw new Exception("缺少对应配置文件"); 43 } 44 45 $xs=new XS($config_path); 46 $this->index =$xs->index; 47 $this->search=$xs->search; 48 49 // 开启模糊搜索 50 //$this->search->setFuzzy(); 51 $this->search->setCharset('UTF-8'); 52 $this->search->setTimeout(0); 53 54 $this->tokenizer = new XSTokenizerScws; 55 } 56 57 public function executeIndex($id,$type){ 58 59 $condition=sprintf($this->table_config[$this->project]["condition"],$id); 60 $field=$this->table_config[$this->project]["use_field"]; 61 $info=M()->table($this->table_config[$this->project]["tablename"])->where($condition)->field($field)->find(); 62 if(empty($info)){ 63 return ["error"=>"1","msg"=>"未找到相关数据"]; 64 } 65 // 创建文档对象 66 $doc = new XSDocument; 67 $doc->setFields($info); 68 switch ($type){ 69 case 'add': 70 // 添加到索引数据库中 71 $this->index->clean(); 72 $this->index->add($doc); 73 break; 74 case "edit": 75 // 更新到索引数据库中 76 $this->index->update($doc); 77 break; 78 case "del": 79 $this->index->del($info[$this->table_config[$this->project]["primary_key"]]); 80 default: 81 break; 82 } 83 $this->index->flushIndex(); 84 return ["error"=>"0","msg"=>"数据处理成功"]; 85 } 86 87 public function executeIndexInfo($arr,$type){ 88 $field_str=$this->table_config[$this->project]["use_field"]; 89 $field_arr=explode(",",$field_str); 90 $info=array(); 91 foreach((array)$field_arr as $value){ 92 if(!isset($arr[$value])){ 93 return ["error"=>"1","msg"=>"未找到相关数据"]; 94 exit; 95 } 96 $info[$value]=$arr[$value]; 97 } 98 99 if(empty($info)){ 100 return ["error"=>"1","msg"=>"未找到相关数据"]; 101 exit; 102 } 103 104 // 创建文档对象 105 $doc = new XSDocument; 106 $doc->setFields($info); 107 switch ($type){ 108 case 'add': 109 // 添加到索引数据库中 110 $this->index->add($doc); 111 break; 112 case "edit": 113 // 更新到索引数据库中 114 $this->index->update($doc); 115 break; 116 default: 117 return ["error"=>"1","msg"=>"未找到相关数据"]; 118 exit; 119 break; 120 } 121 $this->index->flushIndex(); 122 return ["error"=>"0","msg"=>"数据处理成功"]; 123 124 } 125 //清空索引 126 public function cleanIndex(){ 127 $this->index->clean(); 128 return ["error"=>"0","msg"=>"数据处理成功"]; 129 } 130 131 public function rebuildIndex($model=1,$condition=array()){ 132 if($model==1){ 133 // 宣布开始重建索引 134 $this->index->beginRebuild(); 135 $this->addAllIndex($condition); 136 //重建完比 137 $this->index->endRebuild(); 138 return ["error"=>"0","msg"=>"数据重建成功"]; 139 }else{ 140 $this->index->clean(); 141 $this->addAllIndex($condition); 142 $this->index->flushIndex(); 143 return ["error"=>"0","msg"=>"数据重建成功"]; 144 } 145 } 146 147 public function addAllIndex($condition){ 148 $num=0; 149 $page=1000; 150 while(true){ 151 $field=$this->table_config[$this->project]["use_field"]; 152 if($condition){ 153 $list=M()->table($this->table_config[$this->project]["tablename"])->where($condition)->field($field)->page($num.','.$page)->select(); 154 }else{ 155 $list=M()->table($this->table_config[$this->project]["tablename"])->field($field)->page($num.','.$page)->select(); 156 } 157 $num++; 158 if(empty($list)){ 159 break; 160 } 161 162 foreach($list as $value){ 163 $doc = new XSDocument; 164 $doc->setFields($value); 165 $this->index->add($doc); 166 } 167 } 168 } 169 170 public function searchIndexKey($keywords, $page_num, $page_size){ 171 $words = $this->tokenizer->getResult($keywords); 172 $wordsArr=array(); 173 foreach($words as $value){ 174 $wordsArr[]=$value["word"]; 175 } 176 $queryStr = ''; 177 $queryStr.=join(' OR ', $wordsArr); 178 $offset = ($page_num - 1) * $page_size; 179 $this->search->addQueryString($queryStr); 180 $this->search->setLimit($page_size, $offset); 181 $result = $this->search->search(); 182 183 $list = $this->processResult($result,$this->project); 184 $total = $this->search->getLastCount(); 185 186 return array( 187 'list' => $list, 188 'total' => $total, 189 ); 190 } 191 /** 192 * 193 * @param type $keywords 194 * @param type $page_num 195 * @param type $page_size 196 * @return array('total' => int,'list' => array()) 197 */ 198 public function searchIndex($keywords = array(), $page_num = 1, $page_size = 10) 199 { 200 201 $queryStr = ''; 202 if (!empty($keywords)) { 203 $queryStr.=join(' OR ', $keywords); 204 } 205 206 $offset = ($page_num - 1) * $page_size; 207 $this->search->addQueryString($queryStr); 208 $this->search->setSort($this->table_config[$this->project]["primary_key"]); 209 $this->search->setLimit($page_size, $offset); 210 $result = $this->search->search(); 211 212 $list = $this->processResult($result,$this->project); 213 $total = $this->search->getLastCount(); 214 215 return array( 216 'list' => $list, 217 'total' => $total, 218 ); 219 } 220 221 public function processResult($list,$type) 222 { 223 $docs = array(); 224 foreach ($list as $item) { 225 if($type=='company'){ 226 $row['id']=$item['id']; 227 //$row['title']=$this->search->highlight($item['title'],true); 228 $row['title']=$item['title']; 229 $docs[] = $row; 230 }elseif($type==""){ 231 //$row['update_time']=$row['create_time']; 232 //$row['content']=$this->search->highlight($row['content'],true); 233 //$row['title']=$this->search->highlight($row['title'],true); 234 //$docs[] = $row; 235 } 236 } 237 return $docs; 238 } 239 240 241 }