1. 程式人生 > >PHP-elasticsearch配置+基於elasticsearch全文搜尋引擎的開發小結

PHP-elasticsearch配置+基於elasticsearch全文搜尋引擎的開發小結

  • 首先參照官網內容下載與自己php以及elasticsearch版本相匹配的Php-elasticsearch,按照官網內容進行配置https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html

接下來講一下我基於elasticsearch-PHP開發的一個全文搜尋專案

  • 說明一下:PHP使用Codeignite框架,前端以及後端很多東西都是現成的,我只是完成了elasticsearch與mysql資料的同步,以及將資料從elasticsearch按照一定的邏輯提供給前端網頁。
  • 我需要完成的內容是按照搜尋關鍵字、搜尋範圍以及搜尋型別進行排列組合考慮每種可能的情況的解決辦法。中間涉及到elasticsearch bool查詢(should must must not filter 等)

  • 下面截圖是我的全文搜尋涉及到的關鍵字以及hosts(elasticsearch 域名的設定),get_search()函式的引數是從前端傳過來的。elasticsearch按照這些引數完成搜尋。

搜尋函式圖


  • 具體實現是根據這些引數以及前端的需求進行排列組合,對於每一種可能出現的狀況書寫查詢匹配程式碼
  • 下面按照$keys=”name”作為示例講解:
case "name":
        #將搜尋範圍可能的條目列到一個數組中然後進行匹配
        if(in_array($search_category,$category)){
            $params
= [ #這是我elasticsearch中的一個index 'index' => '******', # 上面index對應的type 'type' => '****', 'body' => [ #get_search()函式中的引數, $rows與$offset,作為size與from欄位的引數,這是分頁的部分
"size" => $rows, "from" => $offset, #sort按照時間和_score值進行排序,這個書寫順序表示對於時間日期相同的部分按照_score 值排序 "sort" => [["****" => ["order" => "desc"]], ["_score" => ["order" => "desc"]]], #這是主體查詢部分,bool完成複雜查詢。 "query" => [ "bool" => [ #filter欄位表示先將符合查詢範圍的過濾出來(據說先filter再should查詢,查詢效能會好一些) "filter" => [ ["match" => ["type" => $search_category]]], "should" => [ ["match" => [ "*****"=> $keys]], ["match" => [ "*****" => $keys]]], "must" => [ ["match" => [ "****" => $keys]], ["match" => [ "*****" => $keys]]]]], # 高亮部分,使用"pre_tags"與"post_tags"設定我的高亮style #由於使用PHP-elasticsearch官方版本,需要將需高亮欄位設定為:"****" => new \stdClass才能正確顯示高亮 #fragment_size預設顯示100字,我這裡設定為150 #no_match_size:設定這個欄位是表明如果沒有匹配到也將文字顯示出來,這裡表示150字 "highlight" => [ "pre_tags" => ["<span class='yx_hl'>"], "post_tags" => [ "</span>"], "fields" => [["****" => new \stdClass, "****" => ["fragment_size" => 150], "****" => ["no_match_size" => 150]], ["*****" => new \stdClass, "*****" => ["fragment_size" => 150], "*****" => ["no_match_size" => 150]]]] ]];}

  • 其實對於全文搜尋我自己設定了一個欄位full_field,將所有可能涉及到與搜尋內容相關的欄位都放到這個欄位裡,elasticsearch使用copy_to欄位實現。下面是配置的mapping中的一段:
"full_field":{
                "type":"text",
                #中文分詞,使用ik_smart(相對於ik_max_word ik_smart的分詞效果更符合我的需求一點)
                "analyzer": "ik_smart"},
           "*****": {
            "type": "text",
            "copy_to":"full_field",
             "analyzer": "ik_smart",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }