文章目錄
-
-
- 介紹
- 基本概念
-
- 全文搜尋(Full-text Search)
- 反向索引(Inverted Index)
- 節點&叢集(Node & Cluster)
- 文檔(Document)
- 索引(Index)
- 類型(Type)
- 文檔中繼資料(Document Metadata)
- 字段(Field)
- ElasticSearch與關系型資料庫對應關系
- ElasticSearch與Solr對比
- ElasticSearch安裝
- ElasticSearch Head安裝
- Kibana安裝
- ElasticSearch增删改查
-
- 新增文檔(Index API)
- 修改文檔(Update API)
- 查詢文檔(Get API)
- 删除文檔(Delete API)
- 批量操作(Bulk API)
- 根據多個文檔ID擷取文檔(Multi Get API)
- ES中文分詞器
-
- 内置的标準分詞器standard
- IK分詞器
- 問題
-
- 單機情況下增加索引叢集健康狀态是yellow
- 參考網址
-
介紹
Elasticsearch 是大資料時代下的分布式搜尋引擎,底層基于 Lucene 實作。Elasticsearch 屏蔽了 Lucene 的底層細節,提供了分布式特性,同時對外提供了 Restful API,資料互動格式為JSON。Elasticsearch 以其易用性迅速赢得了許多使用者,被用在網站搜尋、日志分析等諸多方面。由于 ES 強大的橫向擴充能力,甚至很多人也會直接把 ES 當做 NoSQL 來用。
基本概念
全文搜尋(Full-text Search)
全文檢索是指計算機索引程式通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置,當使用者查詢時,檢索程式就根據事先建立的索引進行查找,并将查找的結果回報給使用者的檢索方式。
反向索引(Inverted Index)
該索引表中的每一項都記錄了屬性值與具有該屬性值的記錄的位址。由于不是由記錄找到屬性值而是通過屬性值找到記錄,是以叫作反向索引。譬如歌手張學友唱過《味道》這首歌曲,歌手辛曉琪和吳彥斌也唱過,我們能通過張學友找到他唱了《味道》這首歌曲,但是反過來我們通過《味道》這首歌曲能找到張學友和其他歌手,這樣通過屬性值找到記錄的方法就稱為反向索引,也就是反向索引。
ES是為記錄的每個字段都建立了反向索引,是以才能實作快速高效的搜尋功能。
具體反向索引結構可以參考ElasticSearch反向索引結構分析。
節點&叢集(Node & Cluster)
ElasticSearch本質上就是分布式搜尋引擎,允許多台伺服器協同工作,每台伺服器可以運作多個ElasticSearch執行個體,每個ElasticSearch執行個體就稱為一個節點(
Node
),一組節點就稱為一個叢集(
Cluster
)。
單節點的ES也可以是一個叢集。
文檔(Document)
文檔其實就是使用者送出給ES的一條資料,上面也說過ES資料互動格式都是JSON,是以這裡的文檔就是一條JSON資料。這裡的文檔可以類比成關系型資料庫中的記錄。JSON資料中含有多個字段,JSON裡的字段可以類比成關系型資料庫中表的字段。
索引(Index)
索引(Index)可以了解成文檔的集合,同在一個索引中的文檔共同建立反向索引。
索引(Index)可以類比成關系型資料庫中的庫(Database)。
類型(Type)
文檔可以分組,比如employee這個 Index 裡面,可以按部門分組,也可以按職級分組。這種分組就叫做 Type,它是
虛拟的邏輯分組
,用來過濾 Document,類似關系型資料庫中的資料表。
不同的Type應該有相似的結構,性質完全不同的資料應該存成兩個Index而不是一個Index裡不同的Type。
ES官網提出的Type觀念的演變情況如下
5.x版本中,一個Index下可以建立多個Type
6.x版本中,一個Index下隻能存在一個Type
7.x版本中,去除了Type的概念
8.x版本中,正式棄用
為什麼會被棄用?
因為同一個索引下,
不同type下若字段名是一樣的則ES會認為是一個字段而且類型必須一緻
,因為type隻是一個虛拟的邏輯分組。
不同type的資料存儲其他type的字段大量空值,造成資源浪費
,而且基于Lucene的反向索引是基于Index而不是Type的,多個Type反而會減慢搜尋速度。
文檔中繼資料(Document Metadata)
文檔中繼資料為_index、_type、_id
,這三者可以唯一表示一個文檔。_index表示文檔存放于哪個索引,_type表示文檔的對象類别,_id為文檔的唯一辨別。
字段(Field)
每個文檔都是一條JSON資料,JSON資料中的每個key就是字段(Field)。
ElasticSearch與關系型資料庫對應關系
ES早期是借鑒了關系型資料庫的模式,對應關系如下圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1UDN5EDNyETM3IjMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
對于最新的ES版本而言,由于棄用了Type概念,
一張表就對應一個索引
。
ElasticSearch與Solr對比
二者安裝都很簡單;
Solr 利用 Zookeeper 進行分布式管理,而 Elasticsearch 自身帶有分布式協調管理功能
;
Solr 支援更多格式的資料,而
Elasticsearch 僅支援json檔案格式
;
Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,進階功能多有第三方插件提供;
Solr 在
傳統的搜尋
應用中表現好于 Elasticsearch,但在
處理實時搜尋應用時效率明顯低于
Elasticsearch。
Solr 是傳統搜尋應用的有力解決方案,但 Elasticsearch 更适用于新興的實時搜尋應用。
ElasticSearch安裝
由于國内通路ElasticSearch官網很慢,是以建議從華為開源鏡像站下載下傳。
後續相關内容都以7.6.1版本來學習。并且相關服務都部署在Linux伺服器上。
-
解壓檔案
将檔案放到
目錄下/usr/local/src/packages/es
解壓檔案并建立軟連接配接ElasticSearch 介紹、安裝及簡單使用
cd /usr/local/src
tar zxPvf packages/es/elasticsearch-7.6.1-linux-x86_64.tar.gz
ln -s elasticsearch-7.6.1 elasticsearch
- 建立ElasticSearch啟動使用者并給相關檔案夾賦予權限
useradd es
passwd es
chown -R es:es /usr/local/src/elasticsearch-7.6.1
chown -R es:es /usr/local/src/elasticsearch
- 修改配置檔案
目前主機名是: masterelasticsearch-7.6.1/config/elasticsearch.yml
node.name: node-1
network.host: master
discovery.seed_hosts: ["master"]
- 修改配置檔案
修改後通過/etc/security/limits.conf
檢視是否生效ulimit -Hn 和 ulimit -Sn
* soft nofile 655350
* hard nofile 655350
- 修改配置檔案
并執行/etc/sysctl.conf
重新加載該配置檔案sysctl -p
vm.max_map_count=655360
- 啟動ElasticSearch
cd /usr/local/src/elasticsearch/bin
./elasticsearch
# 或者 ./elasticsearch -d 以背景程序的方式啟動
-
驗證ElasticSearch是否正常
在浏覽器上輸入 http://master:9200/ 得到下圖所示
curl方式通路ElasticSearch 介紹、安裝及簡單使用 curl -XGET "http://master:9200"
ElasticSearch 介紹、安裝及簡單使用
ElasticSearch Head安裝
該工具是GitHub開源的項目elasticsearch-head,能連接配接上ElasticSearch叢集并以可視化的界面呈現資訊。
該項目不僅提供了前端項目連接配接ElasticSearch的方式,也提供了Chrome插件方式,我們此處用Chrome插件方式即可。
插件下載下傳位址是https://raw.githubusercontent.com/mobz/elasticsearch-head/master/crx/es-head.crx
為了能夠臨時解析通路該位址,需要在
C:\Windows\System32\drivers\etc\hosts
檔案添加如下内容,添加後就可以下載下傳了。
199.232.28.133 raw.githubusercontent.com
然後解壓檔案
es-head.crx
打開Chrome浏覽器的擴充程式頁面
chrome://extensions/
并選擇剛剛解壓的檔案夾
es-head
會出現如下圖的插件
點選紅框按鈕即可
在輸入框輸入ElasticSearch的HTTP通路位址,點選連接配接看到如下圖即為正常
Kibana安裝
-
解壓檔案
将檔案放到
目錄下/usr/local/src/packages/es
解壓檔案并建立軟連接配接
cd /usr/local/src
tar zxPvf packages/es/kibana-7.6.1-linux-x86_64.tar.gz
ln -s kibana-7.6.1-linux-x86_64 kibana
- 賦予權限
chown -R es:es /usr/local/src/kibana-7.6.1-linux-x86_64
chown -R es:es /usr/local/src/kibana
- 修改配置檔案
/usr/local/src/kibana-7.6.1-linux-x86_64/config/kibana.yml
server.host: "master"
elasticsearch.hosts: ["http://master:9200"]
i18n.locale: "zh-CN"
- 啟動Kibana,預設端口是
5601
cd /usr/local/src/kibana-7.6.1-linux-x86_64/bin
./kibana
- 在浏覽器上輸入
http://master:5601/
ElasticSearch 介紹、安裝及簡單使用 同時也能在ElasticSearch Head插件看到Kibana自己的索引,如下圖ElasticSearch 介紹、安裝及簡單使用 ElasticSearch 介紹、安裝及簡單使用
ElasticSearch增删改查
新增文檔(Index API)
新增文檔有兩種方式
-
PUT /<index>/_doc/<_id>
-
POST /<index>/_doc/
<index>
必須傳入,如果索引不存在預設情況下會自動建立索引
<_id>
是可選的,如果用
PUT
方法必須要傳入
<_id>
,如果用
POST
方法則會自動生成ID
GET /student/_search
{
"query": {
"match_all": {}
}
}
PUT /student/_doc/1
{
"name": "jackie",
"age": 26,
"school": "ShenZhen University",
"desc": "技術宅, 動漫愛好者, 大資料"
}
POST /student/_doc
{
"name": "marry",
"age": 27,
"sex": "girl",
"desc": "可愛的女生"
}
我們可以在ElasticSearch Head插件裡查詢到剛剛插入的資料
修改文檔(Update API)
POST /<index>/_update/<_id>
可用于更新該文檔的指定字段内容,若想全部更新則可以使用上面提到的
PUT
方法
POST /student/_update/1
{
"doc": {
"sex": "boy",
"age": "28"
}
}
查詢文檔(Get API)
GET <index>/_doc/<_id>
GET /student/_doc/1
删除文檔(Delete API)
DELETE /<index>/_doc/<_id>
DELETE /student/_doc/1
批量操作(Bulk API)
BULK API
就是在單個API調用中執行多個
Index
或
Create
或
Delete
或
Update
操作,減少了開銷,大大提高了索引速度。
但是單個API中到底執行多少個Action性能最好需要根據叢集的配置來實驗優化選擇合适的Action數。
POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
請求格式如下
POST /_bulk
POST /<index>/_bulk
資料格式如下
action_and_meta_data\n
optional_source\n
action_and_meta_data\n
optional_source\n
....
action_and_meta_data\n
optional_source\n
-
和Index
操作期望下一行就是Create
内容。如果文檔source
已存在那麼document
會報錯,Create
則會根據需要更新或添加一個Index
。document
-
操作期望下一行是Update
。partial doc, upsert, and script and its options
-
操作下一行無内容即可。Delete
如批量插入資料
由于我指定了往
lol
這個索引插入資料,是以
action_and_meta_data
沒有顯示指定索引
POST /lol/_bulk
{"index":{"_id": "1"}}
{"heroId":1,"name":"黑暗之女","alias":"Annie","title":"安妮","roles":["mage"],"attack":2,"magic":10,"difficulty":6,"goldPrice":4800,"couponPrice":2000,"keywords":["安妮","黑暗之女","火女","Annie","anni","heianzhinv","huonv","an","hazn","hn"]}
{"index":{"_id": "2"}}
{"heroId":2,"name":"狂戰士","alias":"Olaf","title":"奧拉夫","roles":["fighter","tank"],"attack":9,"magic":3,"difficulty":3,"goldPrice":1350,"couponPrice":1500,"keywords":["狂戰士","奧拉夫","kzs","alf","Olaf","kuangzhanshi","aolafu"]}
{"index":{"_id": "3"}}
{"heroId":3,"name":"正義巨像","alias":"Galio","title":"加裡奧","roles":["tank","mage"],"attack":1,"magic":6,"difficulty":5,"goldPrice":3150,"couponPrice":2000,"keywords":["正義巨像","加裡奧","Galio","jla","zyjx","zhengyijuxiang","jialiao"]}
{"index":{"_id": "4"}}
{"heroId":4,"name":"卡牌大師","alias":"TwistedFate","title":"崔斯特","roles":["mage"],"attack":6,"magic":6,"difficulty":9,"goldPrice":4800,"couponPrice":3000,"keywords":["卡牌大師","崔斯特","卡牌","TwistedFate","kp","cst","kpds","kapaidashi","cuisite","kapai"]}
{"index":{"_id": "5"}}
{"heroId":5,"name":"德邦總管","alias":"XinZhao","title":"趙信","roles":["fighter","assassin"],"attack":8,"magic":3,"difficulty":2,"goldPrice":3150,"couponPrice":2500,"keywords":["德邦總管","德邦","趙信","XinZhao","db","dbzg","zx","debangzongguan","debang","zhaoxin"]}
如批量删除資料
由于我的API裡沒有顯示指定索引,是以在
action_and_meta_data
必須要顯示指定哪個索引
POST /_bulk
{"delete":{"_index": "lol", "_id": "1"}}
{"delete":{"_index": "lol", "_id": "2"}}
{"delete":{"_index": "lol", "_id": "3"}}
{"delete":{"_index": "lol", "_id": "4"}}
{"delete":{"_index": "lol", "_id": "5"}}
如批量更新資料
POST /lol/_bulk
{"update":{"_id": "1"}}
{"doc": {"age": 11}}
{"update":{"_id": "2"}}
{"doc": {"age": 12}}
{"update":{"_id": "3"}}
{"doc": {"age": 13}}
當然批量操作的Action類型是可以混用的。
普通插入的
Curl
語句如下,需要指定請求頭
Content-Type: application/json
但是批量操作如果用
Curl
的方式,則必須将請求資料存入檔案,指定請求頭
Content-Type: application/x-ndjson
,然後使用
--data-binary "@filename"
指定資料檔案。如下所示
根據多個文檔ID擷取文檔(Multi Get API)
Multi Get API
可以根據多個文檔ID批量擷取文檔資料。既可以檢索多個索引的多個文檔,也可以檢索單個索引的多個文檔。
API請求格式如下。
GET /_mget
GET /<index>/_mget
請求體參數如下圖
下面就是通過
/_mget
API批量擷取文檔的例子
GET /lol/_mget
{
"ids": ["1","2","3"]
}
# 隻想擷取指定字段
GET /lol/_mget
{
"docs": [
{
"_id": "1",
"_source": {
"include": ["name", "age"]
}
},
{
"_id": "2",
"_source": {
"include": ["name", "age"]
}
},
{
"_id": "5",
"_source": {
"include": ["name", "age"]
}
}
]
}
GET /lol/_mget
{
"docs": [
{
"_id": "1",
"_source": ["name", "age"]
},
{
"_id": "2",
"_source": ["name", "age"]
},
{
"_id": "5",
"_source": ["name", "age"]
}
]
}
ES中文分詞器
内置的标準分詞器standard
我們以
中華人民共和國國歌
為例進行分詞
# 預設分詞器
# standard whitespace
POST /_analyze
{
"text": "中華人民共和國國歌",
"tokenizer": "standard"
}
如下圖所示,将每個漢字當成了一個
token
IK分詞器
- 安裝
該項目elasticsearch-analysis-ik已在GitHub開源。
由于我們的ElasticSearch版本是7.6.1,是以也需要下載下傳對應版本的IK分詞器。
安裝步驟很簡單,将下載下傳好的
elasticsearch-analysis-ik-7.6.1.zip
放到
/usr/local/src/packages/es
目錄下,将解壓到
es-home/plugins/ik
檔案夾後重新開機ES即可。
# 在ES的HOME/plugins下建立ik檔案夾
su - es
mkdir -p /usr/local/src/elasticsearch-7.6.1/plugins/ik
# 将IK分詞器壓縮包解壓到/usr/local/src/elasticsearch-7.6.1/plugins/ik
su - root
cd /usr/local/src/packages/es
unzip elasticsearch-analysis-ik-7.6.1.zip -d /usr/local/src/elasticsearch-7.6.1/plugins/ik
chown -R es:es /usr/local/src/elasticsearch-7.6.1/plugins/ik
啟動會看到如下加載了插件
loaded plugin [analysis-ik]
的日志
- ik_max_word 分詞
# ik_max_word即最細粒度分詞器,窮盡可能
POST /_analyze
{
"text": "中華人民共和國國歌",
"tokenizer": "ik_max_word"
}
- ik_smart 分詞
# ik_smart即最粗粒度分詞器
POST /_analyze
{
"text": "中華人民共和國國歌",
"tokenizer": "ik_smart"
}
- ik_max_word 和 ik_smart 什麼差別?
ik_max_word: 會将文本做最細粒度的拆分,比如會将“中華人民共和國國歌”拆分為“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合,适合 Term Query;
ik_smart: 會做最粗粒度的拆分,比如會将“中華人民共和國國歌”拆分為“中華人民共和國,國歌”,适合 Phrase 查詢。
-
自定義詞典
我們以
為例進行分詞,我想得到兩個聖槍遊俠盧錫安
即token
和聖槍遊俠
,但是盧錫安
和ik_max_word
都無法得到我想要的結果,是以需要自定義詞典。ik_smart
- 修改配置檔案
添加了兩個詞典檔案ES-HOME/plugins/ik/config/IKAnalyzer.cfg.xml
和custom/my.dic
(編碼格式必須是custom/lol.dic
)UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴充配置</comment>
<!--使用者可以在這裡配置自己的擴充字典 -->
<entry key="ext_dict">custom/my.dic;custom/lol.dic</entry>
<!--使用者可以在這裡配置自己的擴充停止詞字典-->
<entry key="ext_stopwords"></entry>
<!--使用者可以在這裡配置遠端擴充字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--使用者可以在這裡配置遠端擴充停止詞字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
- 在自定義詞典
中添加custom/lol.dic
token
ElasticSearch 介紹、安裝及簡單使用 - 驗證結果
ElasticSearch 介紹、安裝及簡單使用 ElasticSearch 介紹、安裝及簡單使用
問題
單機情況下增加索引叢集健康狀态是yellow
在增加
test
索引後叢集狀态是
yellow
POST /test/_doc
{
"name": "marry",
"age": 27,
"sex": "girl",
"desc": "可愛的女生"
}
這是因為預設自動建立的索引
number_of_replicas=1
即預設副本數為1
由于此處是單機不需要副本,可以通過AP将該索引副本數設定為0即可
# 設定索引的副本數為0
PUT /test/_settings
{
"number_of_replicas": "0"
}
參考網址
ElasticSearch7.6官網文檔
ElasticSearch與Solr對比
ElasticSearch反向索引結構分析
狂神說ES教程
ElasticSearch在Linux上安裝遇到的問題
ElasticSearch中文分詞器
ElasticSearch官網client API