1. 程式人生 > >二十四、ES(elasticsearch)搜尋引擎安裝和使用

二十四、ES(elasticsearch)搜尋引擎安裝和使用


大資料時代,搜尋無處不在。搜尋技術是全棧工程師必備技術之一,如今是開源時代,數不盡的資源供我們利用,如果要自己寫一套搜尋引擎無疑是浪費繩命。本節主要介紹搜尋引擎開源專案elasticSearch的安裝和使用

為什麼需要搜尋引擎

首先想一下:在一篇文章裡找一個關鍵詞怎麼找?字串匹配是最佳答案。

然後再想一下:找到100篇文章裡包含某個關鍵詞的文章列表怎麼找?依然是關鍵詞匹配

再繼續想:找到100000000000(一千億)篇文章裡包含某個關鍵詞的文章怎麼找?如果用關鍵詞匹配,以現在的電腦處理速度,從遠古時代到人類滅絕這麼長時間都處理不完,這時候搜尋引擎要發揮作用了

搜尋引擎技術有多麼高深?

搜尋引擎這種技術實際上從古代就有了。想象一個國家儲存各類編撰資料的部門,有幾個屋子的書,如果想找到某一本書的時候會怎麼找呢?對了,有分類目錄,先確定要找的書籍是哪個類別的,然後從目錄裡面找到想要找的書籍位於屋子的什麼位置,然後再去拿。搜尋引擎其實就是做了生成目錄(也就是索引)的事情。那麼如今的搜尋引擎是怎麼生成索引的呢?

要把網際網路上的資料生成索引,攏共分三步:第一步,把資料編號;第二步,把每篇資料內容切成詞;第三步,把詞和資料編號的對應關係處理成“詞=》編號列表”的形式

這時候你就可以迅速的找到一千億篇文章裡包含某個關鍵詞的文章了,告訴我關鍵詞是什麼,我直接就從索引裡找到了這個詞對應的文章編號列表了,搞定!把需要數萬年才能做完的工作用了不到一秒鐘就搞定了,這就是搜尋引擎的魅力!

當然,上面說的搜尋引擎技術很簡單,但百度數萬工程師也不都是白吃飯的,如果想做好一個搜尋引擎產品需要解決的問題就有很多了:收集網頁時要考慮全、快、穩、新、優的問題,建索引時要考慮質量、效率、賦權、週期、時效性、資源消耗等問題,搜尋的時候要考慮query分析、排序、篩選、展示、效能、廣告、推薦、個性化、統計等問題,整體上要考慮地域性、容災、國際化、當地法律、反作弊、垂直需求、移動網際網路等諸多問題,所以百度大廈徹夜通明也是可以理解的。

開源搜尋引擎

既然搜尋引擎技術這麼複雜,那麼我們何必自尋煩惱了,開源社群為我們提供了很多資源,世界很美好。

說到開源搜尋引擎一定要用的開源專案就是lucene,它不是搜尋引擎產品,而是一個類庫,而且是至今開源搜尋引擎的最好的類庫沒有之一,因為只有它一個。lucene是用java語言開發,基本上涵蓋了搜尋引擎中索引和檢索兩個核心部分的全部功能,而且抽象的非常好,我後面會單獨寫數篇文章專門講lucene的使用。最後強調一遍,它是一個類庫,不是搜尋引擎,你可以比較容易的基於lucene寫一個搜尋引擎。

然後要說的一個開源專案是solr,這是一個完整的搜尋引擎產品,當然它底層一定是基於lucene的,毫無疑問,因為lucene是最好且唯一的搜尋引擎類庫。solr使用方法請看我的另一篇文章《

教你一步步搭建和執行完整的開源搜尋引擎

最後要說的就是elasticSearch,這個開源專案也可以說是一個產品級別的開源專案,當然它底層一定是基於lucene的,毫無疑問,因為lucene是最好且唯一的搜尋引擎類庫,我承認我是唐僧。它是一種提供了RESTful api的服務,RESTful就是直接通過HTTP協議收發請求和響應,介面比較清晰簡單,是一種架構規則。話不多說,下面我就說下安裝方法和簡單使用方法,這樣更容易理解,之後我會單獨講解怎麼讓你的網站利用elasticSearch實現搜尋功能

elasticSearch安裝

從github下載1.7版tag並編譯(選擇1.7版是因為當前我們的網站的symfony2版本還不支援2.x版本,但請放心的用,1.7版是經過無數人驗證過的最穩定版本)

wget https://codeload.github.com/elastic/elasticsearch/tar.gz/v1.7.5

解壓後進入目錄執行

mvn package -DskipTests

這會花費你很長一段時間,你可以去喝喝茶了

編譯完成後會在target/releases中生成編譯好的壓縮包(類似於elasticsearch-1.7.5.zip這樣的檔案),把這個壓縮包解壓放到任意目錄就安裝好了

安裝ik外掛

ik是一箇中文切詞外掛,elasticSearch自帶的中文切詞很不專業,ik對中文切詞支援的比較好。

https://github.com/medcl/elasticsearch-analysis-ik上找到我們elasticSearch對應的版本,1.7.5對應的ik版本是1.4.1,所以下載https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v1.4.1

解壓出的目錄是:

elasticsearch-analysis-ik-1.4.1

進入目錄後執行

mvn clean package

編譯完後依然是在target/releases生成了類似於elasticsearch-analysis-ik-*.zip的壓縮包,把裡面的內容解壓到elasticsearch安裝目錄的plugins/ik下

再把elasticsearch-analysis-ik-1.4.1/config/ik目錄整體拷貝到elasticsearch安裝目錄的config下

修改elasticsearch安裝目錄下的config/elasticsearch.yml,新增:

index:
  analysis:
    analyzer:
      ik:
        alias: [ik_analyzer]
        type: org.elasticsearch.index.analysis.IkAnalyzerProvider
      ik_max_word:
        type: ik
        use_smart: false
      ik_smart:
        type: ik
        use_smart: true

這樣ik就安裝好了

啟動並試用

直接進入elasticsearch安裝目錄,執行

./bin/elasticsearch -d

後臺啟動完成

elasticSearch是通過HTTP協議收發資料的,所以我們用curl命令來給它發命令,elasticSearch預設監聽9200埠

寫入一篇文章:

curl -XPUT 'http://localhost:9200/myappname/myblog/1?pretty' -d '
{
  "title": "我的標題",
  "content": "我的內容"
}'

會收到返回資訊:

{
  "_index" : "myappname",
  "_type" : "myblog",
  "_id" : "1",
  "_version" : 1,
  "created" : true
}

這說明我們成功把一篇文章發給了elasticSearch,它底層會利用lucene自動幫我們建好搜尋用的索引

再寫一篇文章:

curl -XPUT 'http://localhost:9200/myappname/myblog/2?pretty' -d '
{
  "title": "這是第二篇標題",
  "content": "這是第二篇內容"
}'

會收到返回資訊:

{
  "_index" : "myappname",
  "_type" : "myblog",
  "_id" : "2",
  "_version" : 1,
  "created" : true
}

這時我們找到elasticsearch安裝目錄的data目錄下會生成這樣的目錄和檔案:

ls data/nodes/0/indices/myappname/
0  1  2  3  4  _state

不同環境會稍有不同,但是都會生成myappname目錄就對了

檢視所有文章:

curl -XGET 'http://localhost:9200/myappname/myblog/_search?pretty=true' -d '
{
    "query" : {
        "match_all" : {}
    }
}'

這時會把我們剛才新增的兩篇文章都列出來

搜尋關鍵詞“我的”:

curl -XGET 'http://localhost:9200/myappname/myblog/_search?pretty=true' -d '
{
    "query":{
        "query_string":{"query":"我的"}
    }
}'

會返回:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.191783,
    "hits" : [ {
      "_index" : "myappname",
      "_type" : "myblog",
      "_id" : "1",
      "_score" : 0.191783,
      "_source":
{
  "title": "我的標題",
  "content": "我的內容"
}
    } ]
  }
}

搜尋關鍵詞“第二篇”:

curl -XGET 'http://localhost:9200/myappname/myblog/_search?pretty=true' -d '
{
    "query":{
        "query_string":{"query":"第二篇"}
    }
}'

會返回:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.1879082,
    "hits" : [ {
      "_index" : "myappname",
      "_type" : "myblog",
      "_id" : "2",
      "_score" : 0.1879082,
      "_source":
{
  "title": "這是第二篇標題",
  "content": "這是第二篇內容"
}
    } ]
  }
}

如果想檢查ik的切詞效果,可以執行:

curl 'http://localhost:9200/myappname/_analyze?analyzer=ik_max_word&pretty=true' -d'
{
    "text":"中華人民共和國國歌"
}'

通過返回結果可以看出,ik_max_word切詞把中華人民共和國國歌切成了“中華人民共和國”、“中華人民”、“中華”、“華人”、“人民共和國”、“人民”、“共和國”、“共和”、“國”、“國歌”

也就是說我們搜尋這些詞中的任意一個都能把這句話搜到,如果不安裝ik外掛的話,那隻會切成:“中”、“華”、“人”、“民”、“共”、“和”、“國”、“國”、“歌”,不夠智慧,搜尋也不好進行了

講解一下

上面幾條命令都是json形式,elasticSearch就是這麼人性化,沒治了。

這裡面的myappname是你自己可以改成自己應用的名字,這在elasticSearch資料儲存中是完全隔離的,而myblog是我們在同一個app中想要維護的不同的資料,就是你的不同資料,比如文章、使用者、評論,他們最好都分開,這樣搜尋的時候也不會混

pretty引數就是讓返回的json有換行和縮排,容易閱讀,除錯時可以加上,開發到程式裡就可以去掉了

analyzer就是切詞器,我們指定的ik_max_word在前面配置檔案裡遇到過,表示最大程度切詞,各種切,360度切

返回結果裡的hits就是“命中”,total是命中了幾條,took是花了幾毫秒,_score就是相關性程度,可以用來做排序的依據

elasticSearch有什麼用

上面都是json的介面,那麼我們怎麼用呢?其實你想怎麼用就怎麼用,煎著吃、炒著吃、燉著吃都行。比如我們的部落格網站,當你建立一篇部落格的時候可以傳送“新增”的json命令,然後你開發一個搜尋頁面,當你輸入關鍵詞點搜尋的時候,可以傳送查詢的命令,這樣返回的結果就是你的搜尋結果,只不過需要你自己潤色一下,讓展現更美觀。感覺複雜嗎?下一節告訴你怎麼用symfony2的擴充套件來實現部落格網站的搜尋功能