Eggjs筆記:ElasticSearch全文搜索引擎之安裝, 配置中文分詞插件, 以及CRUD操作

關於ES

ElasticSearch 是一個基於 Lucene 的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於 RESTful web 接口。Elasticsearch 是用 Java 開發的,並作爲 Apache 許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索。穩定,可靠,快速,安裝使用方便。可以把ES當做是MongoDB來用,mongodb中也有全文搜索引擎,需要商業付費。

官網:https://www.elastic.co/
下載:https://www.elastic.co/cn/downloads/elasticsearch

配置

  • 安裝java sdk 並配置相應環境變量
  • 下載 elasticsearch :https://www.elastic.co/downloads/elasticsearch
  • 運行 ElasticSearch
    • 下載完成 elasticsearch 包後,把 elasticsearch 包放在一個固定目錄,然後從命令窗口 cd 到elasticsearch 包對應的目錄,運行位於 bin 文件夾中的 elasticsearch.bat(windows舉例)。這將會啓動ElasticSearch 在控制檯的前臺運行,這意味着我們可在控制檯中看到運行信息或一些錯誤信息。並可以使用 ctrl + c 停止或關閉它。
    • 當然最好將es配置到環境變量中去是最方便的了。
  • 啓動 ElasticSearch
    • 在啓動過程中,ElasticSearch 的實例運行會佔用大量的內存,所以在這一過程中,電腦會變得比較慢,需要耐心等待,啓動加載完成後電腦就可以正常使用了。
  • 訪問 ElasticSearch Api
    • 當 ElasticSearch 的實例並運行,您可以使用 localhost:9200,基於 JSON 的 REST API 與 ElasticSearch 進行通信,如果輸入 http://localhost:9200/ 出來如下類似數據,說明我們的ElasticSearch 配置並啓動成功
      {
      	"name": "Johnny",
      	"cluster_name": "elasticsearch",
      	"cluster_uuid": "ObwfDfnTTcWc8pyyiao6fQ",
      	"version": {
      	"number": "7.7.1",
      	"build_flavor": "default",
      	"build_type": "tar",
      	"build_hash": "ad56dce891c901a492bb1ee393f12dfff473a423",
      	"build_date": "2020-05-28T16:30:01.040088Z",
      	"build_snapshot": false,
      	"lucene_version": "8.5.1",
      	"minimum_wire_compatibility_version": "6.8.0",
      	"minimum_index_compatibility_version": "6.0.0-beta1"
      	},
      	"tagline": "You Know, for Search"
      }
      

安裝配置中文分詞工具

  • 默 認 情 況 ElasticSearch 只 適 用 於 英 文 分 詞 , 如 果 要 做 中 文 分 詞 的 話 我 們 要 安 裝elasticsearch-analysis-ik 插件
  • 官方文檔:https://github.com/medcl/elasticsearch-analysis-ik
  • 官方提供了兩種安裝中文分詞工具的方法,具體見README,由於第二種可能因爲版本問題會安裝失敗,所以接下來我們用第一種方式給大家安裝。
  • 安裝配置中文分詞工具
    • 下載中文分詞工具
    • 在分詞工具根目錄創建 plugins/ik 文件
    • 把分詞工具包的內容複製到 plugins/ik 文件裏面
    • 修改配置文件的版本: 編輯plugin-decriptor.properties 修改elasticsearch.version同當前版本即可
    • 這樣做不是百分百的可靠,但是大多數情況下都是可行的,最好是下載相同版本的es和中文分詞插件
    • 安裝完成中文分詞插件後,重新啓動 ElasticSearch

Elasticsearch 中的一些概念

  • 集羣(cluster)

    • 代表一個集羣,集羣中有多個節點(node),其中有一個爲主節點,這個主節點是可以通過選舉產生的,主從節點是對於集羣內部來說的。es 的一個概念就是去中心化,字面上理解就是無中心節點,這是對於集羣外部來說的,因爲從外部來看 es 集羣,在邏輯上是個整體,你與任何一個節點的通信和與整個 es 集羣通信是等價的。
  • 索引(index)

    • ElasticSearch 將它的數據存儲在一個或多個索引(index)中。用 SQL 領域的術語來類比,索引就像數據庫,可以向索引寫入文檔或者從索引中讀取文檔,並通過ElasticSearch 內部使用 Lucene 將數據寫入索引或從索引中檢索數據。【可以把索引當做是數據庫來看待】
  • 文檔(document)

    • 文檔(document)是 ElasticSearch 中的主要實體。對所有使用 ElasticSearch的案例來說,他們最終都可以歸結爲對文檔的搜索。文檔由字段構成。【可以把文檔當做是數據庫的數據來看待】
  • 映射(mapping)

    • 所有文檔寫進索引之前都會先進行分析,如何將輸入的文本分割爲詞條、哪些詞條又會被過濾,這種行爲叫做映射(mapping)。一般由用戶自己定義規則。【可以把映射看成是對索引和類型的配置】
  • 類型(type)

    • 每個文檔都有與之對應的類型(type)定義。這允許用戶在一個索引中存儲多種文檔類型,併爲不同文檔提供類型提供不同的映射。【可以把類型當做是數據庫的表來看待】
    • 注意:從ES 7.0.0 開始,type就被移除了,直接使用去掉type後官方推薦的方式進行操作
    • 參考:https://www.elastic.co/guide/en/elasticsearch/reference/master/removal-of-types.html#removal-of-types
  • 分片(shards)

    • 代表索引分片,es 可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分佈到不同的節點上。構成分佈式搜索。分片的數量只能在索引創建前指定,並且索引創建後不能更改。5.X 默認不能通過配置文件定義分片
  • 副本(replicas)

    • 代表索引副本,es 可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當個某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高 es 的查詢效率,es 會自動對搜索請求進行負載均衡。
  • 數據恢復(recovery)

    • 代表數據恢復或叫數據重新分佈,es 在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啓動時也會進行數據恢復。
    • GET /_cat/health?v #可以看到集羣狀態
  • 數據源(River)

    • 代表 es 的一個數據源,也是其它存儲方式(如:數據庫)同步數據到 es 的一個方法。它是以插件方式存在的一個 es 服務,通過讀取 river 中的數據並把它索引到 es
      中,官方的 river 有 couchDB 的,RabbitMQ 的,Twitter 的,Wikipedia 的,river這個功能將會在後面的文件中重點說到。
  • 網關(gateway)

    • 代表 es 索引的持久化存儲方式,es 默認是先把索引存放到內存中,當內存滿了時再持久化到硬盤。當這個 es 集羣關閉再重新啓動時就會從 gateway 中讀取索引數
      據。es 支持多種類型的 gateway,有本地文件系統(默認),分佈式文件系統,Hadoop的 HDFS 和 amazon 的 s3 雲存儲服務。
  • 自動發現(discovery.zen)

    • 代表 es 的自動發現節點機制,es 是一個基於 p2p 的系統,它先通過廣播尋找存在的節點,再通過多播協議來進行節點之間的通信,同時也支持點對點的交互。
    • 5.X 關閉廣播,需要自定義
  • 通信(Transport)

    • 代表 es 內部節點或集羣與客戶端的交互方式,默認內部是使用 tcp 協議進行交互,同時它支持 http 協議(json 格式)、thrift、servlet、memcached、zeroMQ 等的傳輸協議(通過插件方式集成)。
    • 節點間通信端口默認:9300-9400
  • 分片和複製(shards and replicas)

    • 一個索引可以存儲超出單個結點硬件限制的大量數據。
    • 比如,一個具有 10 億文檔的索引佔據 1TB 的磁盤空間,而任一節點可能沒有這樣大的磁盤空間來存儲或者單個節點處理搜索請求,響應會太慢。
    • 爲了解決這個問題,Elasticsearch 提供了將索引劃分成多片的能力,這些片叫做分片。
    • 當你創建一個索引的時候,你可以指定你想要的分片的數量。每個分片本身也是一個功能完善並且獨立的“索引”,這個“索引” 可以被放置到集羣中的任何節點上。
    • 分片之所以重要,主要有兩方面的原因:
      • 允許你水平分割/擴展你的內容容量
      • 允許你在分片(位於多個節點上)之上進行分佈式的、並行的操作,進而提高性能/吞吐量, 至於一個分片怎樣分佈,它的文檔怎樣聚合回搜索請求,是完全由 Elasticsearch 管理的,對於作爲用戶的你來說,這些都是透明的。
    • 在一個網絡/雲的環境裏,失敗隨時都可能發生。在某個分片/節點因爲某些原因處於離線狀態或者消失的情況下,故障轉移機制是非常有用且強烈推薦的。爲此, Elasticsearch 允許你創建分片的一份或多份拷貝,這些拷貝叫做複製分片,或者直接叫複製。複製之所以重要,有兩個主要原因:
      • 在分片/節點失敗的情況下,複製提供了高可用性。複製分片不與原/主要分片置於同一節點上是非常重要的。因爲搜索可以在所有的複製上並行運行,複製可以擴展你的搜索量/吞吐量
      • 總之,每個索引可以被分成多個分片。一個索引也可以被複制 0 次(即沒有複製)或多次。一旦複製了,每個索引就有了主分片(作爲複製源的分片)和複製分片(主分片的拷貝)。
      • 分片和複製的數量可以在索引創建的時候指定。在索引創建之後,你可以在任何時候動態地改變複製的數量,但是你不能再改變分片的數量。
      • 5.X 默認 5:1 5 個主分片,1 個複製分片
    • 默認情況下,Elasticsearch 中的每個索引分配 5 個主分片和 1 個複製。這意味着,如果你的集羣中至少有兩個節點,你的索引將會有 5 個主分片和另外 5 個複製分片(1 個完全拷貝),這樣每個索引總共就有 10 個分片。

使用 RESTAPI 來操作 ElasticSearch

當 ElasticSearch 的實例並運行,您可以使用 localhost:9200, 基於 JSON 的 REST API 與ElasticSearch 進行通信。在 ElasticSearch 自己的文檔中,所有示例都使用 curl。 但是,當使用 API 時也可使用圖形客戶端(如 Fiddler 或 RESTClient),這樣操作起更方便直觀一些。瀏覽器也提供了操作 ElasticSearch 的插件,我們可以使用火狐瀏覽器裏面提供的 ElasticSearch-Head。比如:火狐瀏覽器的 ElasticSearch-Head。當然在谷歌商店搜索ElasticSearch,也有相關的插件可以使用,非常方便。另外,聽說 Chrome 插件 Sense。 Sense 提供了一個專門用於使用 ElasticSearch 的 REST API 的簡單用戶界面,不過這個沒用過,還是推薦使用 ElasticSearch-Head 插件。

上述請求將執行最簡單的搜索查詢,匹配服務器上所有索引中的所有文檔。針對ElasticSearch 運行,Sense 提供的最簡單的查詢,在響應結果的數據中並沒有查詢到任何數據,因爲沒有任何索引。如下所示 :

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 0,
        "successful": 0,
        "failed": 0
    },
    "hits": {
        "total": 0,
        "max_score": 0,
        "hits": []
    }
}

下一步我們來學習添加一些數據和索引,來修復這個問題。

先看看幾個重要概念

索引 數據庫
類型
文檔 數據
映射 對索引類型的配置

創建索引

點擊界面上的索引,新建索引, 如下圖:(圖片託管於github, 請確保網絡的可訪問性)

這樣索引就創建成功了,也就是類比數據庫創建成功了,之後我們需要創建類型和映射,也就是表和配置信息

創建類型以及配置映射

如下圖:(圖片託管於github, 請確保網絡的可訪問性)

// PUT /news/_mapping
{ 
    "properties": { 
        "content": { 
            "type": "text", 
            "analyzer": "ik_max_word", 
            "search_analyzer": "ik_max_word"
        }
    }
}

這裏news是索引, 這裏使用post或者put都可以,_mapping可以放在上面,也可以放在下面(第二行, 如上圖)

注意:關於analyzer

ik_max_word 和 ik_smart 什麼區別?
ik_max_word: 會將文本做最細粒度的拆分,比如會將“中華人民共和國國歌”拆分爲“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合,適合 Term Query;
ik_smart: 會做最粗粒度的拆分,比如會將“中華人民共和國國歌”拆分爲“中華人民共和國,國歌”,適合 Phrase 查詢

摘自README

全文搜索的原理是:對於一段文字, 把它差分成一個個的詞,對這些詞建立索引,速度快的原因是犧牲空間換時間

查看映射

如下圖:(圖片託管於github, 請確保網絡的可訪問性)

// GET /news/_mapping
{}

增加數據

如下圖:(圖片託管於github, 請確保網絡的可訪問性)

// POST /news/_create/1
{"content":"美國留給伊拉克的是個爛攤子嗎"}

// 更多插入,如下:

// POST /news/_create/2
{"content":"公安部:各地校車將享最高路權"}

// POST /news/_create/3
{"content":"中韓漁警衝突調查:韓警平均每天扣1艘中國漁船"}

// POST /news/_create/4
{"content":"中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"}

使用_create來創建數據,後面的 1,2,3,4 都表示id, 當然可以用任意的一串字符串作爲id也是可行的

查詢數據

1.查詢全部(注意:這裏get,post都可以)

// GET /news/_search
// POST /news/_search

2.條件查詢(注意:這裏只能post操作)

// POST /news/_search
{
  "query": {
    "match": {
      "content": "中國"
    }
  },
  "highlight": {
    "pre_tags": [
      "<tag1>",
      "<tag2>"
    ],
    "post_tags": [
      "</tag1>",
      "</tag2>"
    ],
    "fields": {
      "content": {}
    }
  }
}

如下圖:(圖片託管於github, 請確保網絡的可訪問性)

這裏的tag標籤可自定義,用於高亮顯示搜索匹配的關鍵詞,可替換成<i></i>, <u></u> 甚至任何你想用的字母組合<xxx></xxx>

修改數據

這裏修改id爲1的數據

// PUT /news/_doc/1/
{
  "content": "美國留給伊拉克的是個爛攤子嗎 -test update!"
}

注意:這裏的 _doc 必須要填寫,表示數據,下面的刪除也是一個道理

如下圖:(圖片託管於github, 請確保網絡的可訪問性)

查詢測試,如下圖:(圖片託管於github, 請確保網絡的可訪問性)

可以看到查詢出來了,數據已經被成功修改

刪除數據

刪除id爲2的數據

// DELETE /news/_doc/2/

如下圖:(圖片託管於github, 請確保網絡的可訪問性)

再次查詢已經沒有id爲2的,那條"公安部:各地校車將享最高路權"數據了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章