1 <?php
2 namespace Service\Tools;
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 }