PHP-從零開始使用Solr搜尋引擎服務(下)

流火行者發表於2017-07-14

前言:

原文地址:

http://www.cnblogs.com/JimmyBright/p/7156085.html

前面在配置完成Solr服務之後,在瀏覽器上可以開啟Solr的管理介面,這個介面幾乎包含了Solr的所有功能,如何反應到我們的PHP裡邊呢?很多人或許查到需要再安裝一個php-solr-client,用於php和java的solr伺服器通訊,研究了半天沒弄明白怎麼做,反正是很麻煩而且似乎很多餘。

1:思路:

注意看Solr的管理介面上,你或許有以下發現。

上面框框中有一個url地址,把這個地址複製,然後放在瀏覽器的位址列,果然如所想一樣,返回了結果集。市面上有很多Solr教程,厚厚的一本書,裡邊講解肯定很全面,我們沒時間看,怎麼能最快解決問題就怎麼做。

只要瀏覽器上能出結果,很自然就想到,Solr這是對外公開了一套api嘛,我們完全可以用php的curl做到這一點,瀏覽器能做到的,curl肯定也可以。

這裡寫了一個簡單的CURL請求方法

    private  function getCurl($url){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL,$url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $data = curl_exec($curl) ;
        curl_close($curl);
        return json_decode($data,true);
    }

實驗一下,和預期的結果完全一樣,所以下面我們就用這個思路去對接php和solr。

2:使用PHP操作Solr查詢

對應Solr管理介面上的Query欄目下,我們要搞清楚這些欄位的意義,然後就能用php操作整個搜尋過程了

圖中q、fq、sort、fl、df等,這些欄位都是搜尋用的欄位,我們只要搞清楚這些欄位意義就可以寫php程式碼了。

欄位的意義網上有很多,這個連結都有介紹了

http://blog.csdn.net/zmken497300/article/details/52817825

3:使用PHP操作Solr建立索引
搜尋已經有思路去解決了,還有一個關鍵的問題要解決,Solr是對關聯的資料庫建立索引,再對索引進行搜尋
。很顯然資料庫任何時間都會變更,所以要讓Solr能不間斷的重建索引才能搜尋到最新的結果集。
管理介面中有一個Dataimport選項,點開可以手動重建索引,我們沒有看到類似Query上的查詢有一個
URL,我們很希望有這一個東西,這樣就能用curl,程式自動重建索引。
按照前面的思路,我們有理由相信,Solr肯定已經有這樣的api。
把瀏覽器設定除錯模式

當我點下Execute按鈕的時候,看到下面網路請求果然發出了一條url,複製這個url到瀏覽器,和想象的一樣,自動重建了索引並返回了結果列印到瀏覽器上。

到此為止,已經基本都解決了PHP操作Solr的技術問題,可以預見,完成一個簡單的搜尋功能,不會再出現技術問題了吧。

下面附上一段PHP程式碼,操作Solr

 1 class SolrClient
 2 {
 3     public  $query_url='';
 4     public  $import_url='';
 5     private $q='q=*:*';
 6     private $fq='';
 7     private $sort='';
 8     private $rows='rows=10&start=0';
 9     private $fl='';
10     private $raw_query='';
11     public  $hl_str='';
12 
13     function  __construct($core)
14     {
15         $host=Yii::$app->params['solr_host'];
16         $this->query_url=sprintf("%s/solr/%s/select?indent=on&wt=json&",$host,$core);
17         $this->import_url=sprintf("%s/solr/%s/dataimport?indent=on&wt=json&command=full-import&verbose=false&clean=true&commit=true&optimize=false&core=crm&name=dataimport",$host,$core);
18     }
19     public function setQuery(array $query){
20         $q_str=[];
21         foreach ($query as $k=>$v) {
22             if(!empty($v)){
23                 $q_str[]=urlencode($k).':'.urlencode($v);
24             }
25         }
26         if(!empty($q_str)){
27             $this->q='q='.implode(urlencode(' OR '),$q_str);
28         }
29     }
30     public function setFilterQuery(array $query){
31         $q_str=[];
32         foreach ($query as $k=>$v) {
33             $q_str[]='fq='.urlencode($k).':'.urlencode($v);
34         }
35         $this->fq=implode('&',$q_str);
36     }
37     public function setRows($start,$rows){
38         $this->rows=sprintf('rows=%s&start=%s',$rows,$start);
39     }
40     public function setHighLight(array $fields,$hlpre,$hlpost){
41         $hl_fl=[];
42         foreach ($fields as $field) {
43             $hl_fl[]=$field;
44         }
45         $this->hl_str=sprintf("hl.fl=%s&hl.simple.post=%s&hl.simple.pre=%s&hl=on",implode(',',$hl_fl),urlencode($hlpost),urlencode($hlpre));
46     }
47     public function setFl(array $fields){
48         $hl_fl=[];
49         foreach ($fields as $field) {
50             $hl_fl[]=$field;
51         }
52         $this->fl='fl='.implode(',',$hl_fl);
53     }
54     public function setRawQuery(array $params){
55         $raw=[];
56         foreach ($params as $k=>$v) {
57             $raw[]=$k.'='.$v;
58         }
59         $this->raw_query=implode('&',$raw);
60     }
61     public function sortQuery($field,$sort){
62         $this->sort= "sort=".$field.urlencode(' ').$sort;
63     }
64 
65     /**
66      * 搜尋查詢
67      * @return mixed
68      */
69     public function search(){
70         $this->query_url.=$this->q;
71         !empty($this->fq)&&$this->query_url.='&'.$this->fq;
72         !empty($this->sort)&&$this->query_url.='&'.$this->sort;
73         !empty($this->rows)&&$this->query_url.='&'.$this->rows;
74         !empty($this->fl)&&$this->query_url.='&'.$this->fl;
75         !empty($this->raw_query)&&$this->query_url.='&'.$this->raw_query;
76         !empty($this->hl_str)&&$this->query_url.='&'.$this->hl_str;
77         return $this->getCurl($this->query_url);
78     }
79 
80     /**
81      * 全量重構索引
82      * @return mixed
83      */
84     public  function index(){
85         return $this->getCurl($this->import_url);
86     }
87     private  function getCurl($url){
88         $curl = curl_init();
89         curl_setopt($curl, CURLOPT_URL,$url);
90         curl_setopt($curl, CURLOPT_HEADER, 0);
91         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
92         $data = curl_exec($curl) ;
93         curl_close($curl);
94         return json_decode($data,true);
95     }
96 
97 }
View Code

search方法就是用來發起CURL的搜尋命令,當然在這之前,你需要使用其他方法設定你的查詢條件什麼的。

index方法就是用來發起CURL的重建索引命令,把這個方法放在crontab 定時任務裡,就可以定時重建索引,我這裡是全量重建索引,如果你的資料量很大,對新內容的搜尋時效性也要求很高,那麼可以使用增量索引,怎麼做呢?看下管理介面,操作一下,然後除錯模式抓取發出的請求連線,簡單吧。

結束:

至此,就可以完成一個企業級的搜尋服務了,下面貼上我給前端寫的一個搜尋介面,僅供參考!

 1  public function actionSearch(){
 2         $input = $this->getParam('input');
 3         $page  = $this->getParam('page')-1;
 4         empty($page)&&$page=0;
 5         $pageLength=200;
 6         $page<0&&$page=0;
 7         $startRow = $page*$pageLength;
 8         $params=['content_txt'=>$input,'title'=>$input];
 9         $solr = new SolrClient('crm');
10         $solr->setQuery($params);
11         $solr->setRows($startRow,$pageLength);
12         $solr->setFl(['id','title','create_time','content','content_txt','keyword','description','sid','mask_status','type','article_type','item_type','sequence']);
13         $solr->setHighLight(['title','content_txt'],"<b style='color: #f15353;'>","</b>");
14         $data = $solr->search();
15         $response=&$data['response'];
16         $highlighting=&$data['highlighting'];
17         $docs = &$response['docs'];
18         empty($docs) && $this->jsonReturn(0,'搜尋成功',['totalpage'=>0,'totalcount'=>0,'pagesize'=>$pageLength, 'list'=>[]]);
19         foreach ($docs as &$doc) {
20             $id = $doc['id'];
21             $hlItem = $highlighting[$id];
22             $doc['content']=mb_substr($doc['content_txt'],0,200);
23             if(!empty($hlItem)){
24                 if(!empty($hlItem['title'])){
25                     if(!empty($hlItem['title'][0])){
26                         $doc['title']=$hlItem['title'][0];
27                     }
28                 }
29                 if(!empty($hlItem['content_txt'])){
30                     if(!empty($hlItem['content_txt'][0])){
31                         $doc['content']=$hlItem['content_txt'][0];
32                     }
33                 }
34             }
35             unset($doc['content_txt']);
36         }
37         $res=[
38             'totalpage'=>ceil($response['numFound']/$pageLength),
39             'totalcount'=>$response['numFound'],
40             'pagesize'=>$pageLength,
41             'list'=>$response['docs'],
42         ];
43         $this->jsonReturn(0,'搜尋成功。',$res);
44     }
View Code

然後附上一個簡單粗糙的demo頁面

 

相關文章