Elasticsearch構建全文搜索系統

  • 2020 年 3 月 15 日
  • 筆記

前言

Elasticsearch 是一個分散式、可擴展、實時的搜索與數據分析引擎,通過它我們可以構建出一個強大的全文搜索系統,解決諸如文章檢索慢,商品檢索慢、MySQL的like查詢慢這樣的問題。
Elasticsearch是基於hadoop創始人道哥的另一傑作Lucene實現的,速度非常快,核心是使用了倒排索引這樣的結構。關於倒排索引是什麼,可以參考搜索引擎中的倒排索引是什麼
接下來,就以這篇倒排索引中的例子,演示一下ElasticSearch的使用

假設我們有海量文章,如下

頁碼 內容
1 生命在於運動
2 運動是生命的源泉
3 日復一日地堅持練下去吧,只有活動適量才能保持訓練的熱情和提高運動的技能.——塞涅卡
4 活動是生活的基礎!——歌德
5 人的健全,不但靠飲食,尤靠運動
6 奧林匹克的格言是「更高,更快,更強」
7 身體的健康因靜止不動而破壞,因運動練習而長期保持.——蘇格拉底
8 chenqionghe喜歡運動,繩命是如此的精彩,繩命是如此的輝煌

我們想像這是千萬級別的表,最後需要實現傳入關鍵字,返回相應的文章
例如:搜索運動返回頁碼1,2,3,5,7,8對應的文章、搜索chenqionghe返回頁碼為8的文章

一、安裝

1.安裝es

查看官網地址,直接下載安裝就行了,我用的是mac直接下了mac版本的,另外也可以使用dokcer安裝
解壓後長這樣

es依賴java環境,需要指定jdk版本,我們加入一下java相關環境變數

export JAVA_HOME=/Users/chenqionghe/web/elk/elasticsearch-7.6.1/jdk.app/Contents/Home/  export PATH=$JAVA_HOME/bin:$PATH

啟動一下看看

./bin/elasticsearch

看到啟動報錯

uncaught exception in thread [main]  ElasticsearchException[Failure running machine learning native code. This could be due to running on an unsupported OS or distribution, missing OS libraries, or a problem with the temp directory. To bypass this problem by running Elasticsearch without machine learning functionality set [xpack.ml.enabled: false].]

解決辦法,修改./config/elasticsearch.yml添加

 xpack.ml.enabled: false

再次啟動,成功運行,畫風如下

默認啟動的是9200埠,我們來測試一下

➜ ~ curl localhost:9200

yeah, it's running,you konw, for search !

2.啟動集群

編輯./config/elasticsearch.yml
指定集群名稱,這裡注釋打開,集群名稱指定成了chenqionghe

cluster.name: chenqionghe

指定節點名稱

ode.name: chenqionghe-1

設置初始化的節點

cluster.initial_master_nodes: ["chenqionghe-1"]

設置監聽的埠,這裡不限定ip,指定為0.0.0.0

network.host: 0.0.0.0

埠默認9200

http.port: 9200

添加支援elasticsearch-head介面參數

http.cors.enabled: true  http.cors.allow-origin: "*"  http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETE  http.cors.allow-headers: "X-Requested-With, Content-Type, Content-Length, X-User"

再次啟動

./bin/elasticsearch

3.安裝管理介面

elasticsearch-head可以很方便的查看es集群狀態,查看官網地址:elasticsearch-head

git clone git://github.com/mobz/elasticsearch-head.git  cd elasticsearch-head  npm install  npm run start

打開http://localhost:9100/,如下

4.安裝分詞插件

插件我們使用的是elasticsearch-analysis-ik,參考地址:elasticsearch-analysis-ik/

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.1/elasticsearch-analysis-ik-7.6.1.zip

驗證一下分插件

curl -X POST "localhost:9200/_analyze?pretty" -H 'Content-Type: application/json' -d '{ "analyzer": "ik_smart", "text": "chenqionghe徒手健身" }'

可以看到,已經可以分詞了,oh yeah~

二、使用

ES中有index、document、filed、mapping這樣的概念,我們以MySQL的結構為參考對照一下,如下

ElasticSearch MySQL
Iindex 表
document 行
field 列
mapping 表結構

Elasticsearch主要還是使用API,具體使用請參考:Document APIs

1.創建索引

這裡index我取名叫book

➜ ~ curl -X PUT "localhost:9200/book" -H 'Content-Type: application/json' -d '{          "mappings": {                  "properties": {                          "page": {                                  "type": "long"                          },                          "content": {                                  "type": "text",                                  "analyzer": "ik_max_word",                                  "search_analyzer": "ik_max_word"                          }                  }          }  }'  {"acknowledged":true,"shards_acknowledged":true,"index":"book"}

創建成功,但是查看head介面,但是這個黃色不怎麼優雅呀,原因是雖然啟用了集群,但是還是單節點運行的,群集無法放置副本。

集群的健康狀況為 yellow 則表示全部主分片(number_of_shards)都正常運行,但是副本分片沒有全部處在正常狀態,單節點無論有多少個副本分片(number_of_replicas)都是 unassigned ,它們都沒有被分配到任何節點。
在同一個節點上既保存原始數據又保存副本是沒有意義的,因為一旦失去了那個節點,我們也將丟失該節點上的所有副本數據。
我們需要把這個副本設置為0,因為索引一旦建立,分片數量不能變,我們需要刪除再重新建立一下索引

curl -XDELETE http://localhost:9200/book  curl -X PUT "localhost:9200/book" -H 'Content-Type: application/json' -d '{          "settings":{              "number_of_shards": "1",              "number_of_replicas": "0"            },          "mappings": {                  "properties": {                          "page": {                                  "type": "long"                          },                          "content": {                                  "type": "text",                                  "analyzer": "ik_max_word",                                  "search_analyzer": "ik_max_word"                          }                  }          }  }'

再次查看,健康了

2.插入數據

curl -X POST "localhost:9200/book/_doc/" -H 'Content-Type: application/json' -d '{          "page":1,          "content": "生命在於運動"  }'

我們可以看到已經成功插入一條數據

3.批量插入數據

curl -X POST "localhost:9200/book/_doc/_bulk?pretty"  -H 'Content-Type: application/json' -d'  { "index":{} }  { "page":2 , "content": "運動是生命的源泉"}  { "index":{} }  { "page":3 , "content": "日復一日地堅持練下去吧,只有活動適量才能保持訓練的熱情和提高運動的技能.——塞涅卡"}  { "index":{} }  { "page":4 , "content": "活動是生活的基礎!——歌德"}  { "index":{} }  { "page":5 , "content": "人的健全,不但靠飲食,尤靠運動"}  { "index":{} }  { "page":6 , "content": "奧林匹克的格言是「更高,更快,更強」"}  { "index":{} }  { "page":7 , "content": "身體的健康因靜止不動而破壞,因運動練習而長期保持.——蘇格拉底"}  { "index":{} }  { "page":8 , "content": "chenqionghe喜歡運動,繩命是如此的精彩,繩命是如此的輝煌"}  '

可以看到成功批量插入

4.查詢數據

  • 搜索chenqionghe
curl -s -X GET 'localhost:9200/book/_search?pretty' -H 'Content-Type: application/json' -d '{    "query" : { "match" : { "content" : "chenqionghe" }}  }'|jq

可以看到匹配到了

  • 搜索運動,應該是會返回1,2,3,5,7,8這幾條
curl -s -XGET 'localhost:9200/book/_search?pretty' -H 'Content-Type: application/json' -d '{    "query" : { "match" : { "content" : "運動" }}  }'|jq .hits.hits|jq '.[]._source'

可以看到,驗證通過

5.修改數據

拉下來,我們將chenqionghe這條記錄的繩命改為生命,

curl -X POST "localhost:9200/book/_doc/HFn_2XABkofzJYzpQIy4" -H 'Content-Type: application/json' -d '{      "page":8,      "content": "chenqionghe喜歡運動,生命是如此的精彩,生命是如此的輝煌"  }'

可以看到,更新成功

6.刪除數據

  • 根據id刪除
curl -X DELETE "localhost:9200/book/_doc/GFn_2XABkofzJYzpQIy4"
  • 根據條件刪除
curl -X POST "localhost:9200/book/_delete_by_query?pretty" -H 'Content-Type: application/json' -d'  {    "query": {      "match": {        "content": "chenqionghe"      }    }  }  '

7.索引關閉和開啟

如果關閉了一個索引,就無法通過ES來讀取和寫入其中的數據,直到道再次打開它

# 關閉  curl -XPOST 'localhost:9200/book/_close'  # 開啟  curl -XPOST 'localhost:9200/book/_open'

總結

通過Elasticsearch,我們可以快速構建出一個強大的全文搜索系統,安裝簡單,通過API使用也簡單。
倒排索引為搜索而生,先對需要索引的欄位進行分詞,再通過詞直接匹配出文檔,速度非常快,這是優點。但是,相比資料庫採用的 B 樹索引,它的寫入和更新性能都比較差,因此倒排索引也只是適合全文搜索,不適合更新頻繁的交易類數據。
總之,安裝使用Elasticsearch其實就是這麼簡單,驚不驚喜,意不意外呀,light weight baby!

更多資料請參考 :Eelasticsearch權威指南

Tags: