Elastic Search 新手筆記(1)——入門篇
前言
之前寫過一個關於Elastic Search的文章,當時的我還不會使用markdown,還不知道怎麼好好把自己所想的,總結成一個有條理的文章,所以我就想寫下了這一篇新文章,幫助自己消化所學的東西,也可以把知識分享給大家。
使用 | 版本 |
---|---|
作業系統 | MacOS |
ES版本 | 6.3.0 |
視覺化外掛 | Head |
安裝
1.單例項安裝
elasticSearch 的安裝我覺得相對簡單一些,我們可以在官網或者是別的途徑,下載到它,官網的下載地址為https://www.elastic.co/downloads/elasticsearch,當前最新的版本為6.4.2。而我使用的版本是6.3.0,如果想要下載到原來版本的ES,可以進入以下網址進行下載
2.Head外掛安裝
Head外掛是依託於node環境的,我們在使用外掛之前需要先下載node.js。node.js下載好後,通過node -v 檢視是否安裝成功,然後就可以通過以下網址下載Head外掛。Head 外掛地址。下載好Head外掛以及elasticsearch後,需要修改在elasticsearch 中的config的elasticsearch.yml中加上以下配置內容:
http.cors.enabled: true
http.cors.allow-original: "*"
保證了Es以及Head外掛的連通性。 Head外掛的啟動 1.npm install [email protected] --ignore-scripts(之所以不使用npm install 是因為這個包,一直都取不到,但是它也不怎麼影響使用。) 2.npm install 3.npm run start 啟動後,在瀏覽器輸入http://localhost:9100,如果顯示了相關內容即可。
3.分散式安裝
分散式的安裝和單例項安裝大同小異,把下載下來的ElasticSearch複製兩個副本,放在新建立的目錄ES_slave(slave為隨從奴隸的意思,在這裡把我們之前安裝好的當做一個master,然後其他的slave配合master形成一套分散式)中,如下圖所示:
#配置ElasticSearch的叢集名稱
cluster.name: harry
#節點的名稱(另一個節點名稱可以使用slave2)
node.name: slave1
#設定繫結的IP地址
network.host: 127.0.0.1
#設定對外服務的埠號,預設情況下為9200(這裡只要使用沒被使用的埠號即可)
http.port: 8200
#設定是否開啟多播發現節點,如果不進行配置,不會被主節點發現。
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
配置好後,啟動slave的elasticsearch即可。 Tips:我啟動的時候報了一個錯誤。
[2018-10-07T11:57:44,907][INFO ][o.e.d.z.ZenDiscovery ] [slave1] failed to
send join request to master [{master}{dLNpAPsSTvCFgzow1nuM6g}
{lZIG2Xm3Sx-4Y4eHU5x9CA}{127.0.0.1}{127.0.0.1:9300}
{ml.machine_memory=8589934592, ml.max_open_jobs=20,
xpack.installed=true, ml.enabled=true}], reason
[RemoteTransportException[[master][127.0.0.1:9300]
[internal:discovery/zen/join]]; nested: IllegalArgumentException[can't add node
{slave1}{dLNpAPsSTvCFgzow1nuM6g}{4NUyj79cSxuaJL8BMtGejw}{127.0.0.1}
{127.0.0.1:9301}{ml.machine_memory=8589934592, ml.max_open_jobs=20,
xpack.installed=true, ml.enabled=true}, found existing node {master}
{dLNpAPsSTvCFgzow1nuM6g}{lZIG2Xm3Sx-4Y4eHU5x9CA}{127.0.0.1}
{127.0.0.1:9300}{ml.machine_memory=8589934592, xpack.installed=true,
ml.max_open_jobs=20, ml.enabled=true} with the same id but is a different
node instance]; ]
因為我是把master的Es複製過來,作為slave,但是data中還有原來的資料,所以報了這個錯,只要把,Es中的data資料夾中的東西都刪除就行。
我們現在把master 的ES啟動,slave1的ES啟動,slave2的ES啟動,最後把Head也啟動起來,然後瀏覽器輸入http://localhost:9100,效果如下,證明成功。
基本概念
1.索引,型別,文件
Elastic Search 與關係型資料庫對比
Elastic Search | 關係型資料庫 |
---|---|
索引 | 資料庫 |
型別 | 表 |
文件 | 行 |
這裡的Elastic Search 泛指的是全文檢索。一個索引中,包含多個型別,一個型別中包含著多個文件。 在剛接觸的時候,我想過這樣一個問題,在關係型資料庫mysql的like進行模糊查詢的效果,與Elastic Search這樣的全文檢索,效果幾乎就是一樣的,那為什麼還要用全文檢索呢? 原因我覺得一共有兩個: 第一個是查詢的速度特別快。在關係型資料庫中,資料是結構化的,我們當要進行模糊查詢的時候,會從想要查詢的表的第一條資料開始比對,如果不是,繼續下一條,如果再不是,繼續去查,就這樣一直查下去,直到查到了,自己想要的那條資料。而Elastic Search呢?它其實使用了倒排索引。大概意思其實是這樣的:現在一個有三篇文章
id | content |
---|---|
文章1 | Java是世界上最好的 . |
文章2 | 人生苦短,快學python |
文章3 | C++是世界上最難的 . |
這也是儲存在關係型資料庫中的儲存形式,查詢的話,他會一行行的進行查詢。而如果存在了Elastic Search 中會變成什麼樣子呢?在全文檢索中存在這分詞器這麼個東西,分詞器會把輸入的句子自動的進行一定規律進行分割,例如過空格分割,下劃線分割,等等。如果是中文,也有外掛可以對其進行語義分割。分割後的效果如下所示(只是舉例子,真實情況未必如此)
關鍵詞 | 文章號 |
---|---|
世界 | 1,3 |
人生苦短 | 2 . |
Java | 1 . |
python | 2 |
C++ | 3 |
當我們輸入世界,立刻就知道出現在了第一個,和第三個文章中。 第二個是因為我們在做全文檢索的時候,根本用不到那麼複雜的邏輯,我們用到基礎的增刪改查就行,使用了Elastic Search 之後,我們在也不用折騰資料庫那麼多的資料了。
2.分片與索引
每一個索引包含了多個分片,每個分片是一個lucene索引(lucene是Elasticsearch的底層引擎。)只需要將分片拷貝一份,就完成了分片的備份。
3.叢集和節點
每一個叢集都有一個叢集的名字,一個叢集包含多個節點。我們只需要知道叢集的名稱,便可以拓展叢集中的節點。
4.elasticsearch.yml
我上面在啟動head外掛和設定分散式叢集的時候,有修改過這個檔案,但是這個檔案還有別的可配置屬性,我在這裡說明一下,以備不時之需。
cluster.name: elasticsearch
#設定叢集名稱,一個叢集只可以有一個名稱,ElasticSearch會自己去查詢同一個網段下的所有節點
node.name: node-1
#設定節點名稱
node.master: true
#設定該節點是否是master節點,預設為true
node.data: true
#設定該節點,是否儲存索引資料,預設為true
index.number_of_shards: 5
#設定分片的數量,預設為5個,這個配置只在5.0版本之前好用
index.number_of_replicas: 1
#設定索引副本數量,預設為一個,同樣也是隻在5.0之前好用。
path.data: /path/to/data
#設定索引資料的儲存路徑,預設在data資料夾下,可以設定多個檔案儲存路徑,用逗號分隔。
path.logs: /path/to/logs
#設定log日誌的儲存路徑,預設情況下是在logs資料夾下。
bootstrap.mlockall: true
#設定為true來鎖住記憶體
network.host: 0.0.0.0
#設定繫結的Ip地址,預設為0.0.0.0
http.port: 9200
#設定對外服務的HTTP埠號
transport.tcp.port: 9300
#設定節點間互動的TCP埠號,也是給Java API使用的埠號,預設是9300。
transport.tcp.compress: false
#是否壓縮TCP傳輸的資料,預設為false
http.cors.enabled:true
#是否使用http提供對外的服務,預設為true
http.max_content_length: 100mb
#http傳輸內容的最大容量。
discovery.zen.minimum_master_nodes: 1
#發現master節點的數量,預設為1個。
discovery.zen.ping.timeout: 3s
#發現其他節點,超時的時間。
discovery.zen.ping.multicast.enabled:true
#是否開啟多播發現節點。
discovery.zen.ping.unicast.hosts:["host1","host2:port","host3:[portX-portY]"]
#設定叢集master幾點的初始列表。
script.engine.groovy.inline.update: on
#開啟groovy指令碼的支援
script.inline: true
#開始所有指令碼語言行內執行所有的操作。
基本用法
Elastic Search 我們可以使用REST API與其進行互動,說白了就是使用url地址,通過不同的method(get,post,put,delete)傳入不同的json資料。 head外掛雖然很好,但是也並不是萬能的,我比較習慣用Post man進行api互動。下面講講具體的操作。 1.建立索引
url地址 | method | 用途 |
---|---|---|
localhost:9200/索引名稱 | put | 建立索引 |
在建立索引之前,我要先說兩個概念分別是靜態對映和動態對映。 動態對映是在建立索引之初,不新增索引的型別和文件中屬性的格式,而是在新增文件的時候,格式會被自動轉化。兩種不同對映的設定,是由dynamic引數來決定的一共有三個可選值:
- true 動態對映自動新增欄位
- false 靜態對映,不會自動新增欄位
- strict 靜態對映,如果添加了新欄位會報錯
動態轉換內容如下:
JSON格式的資料 | 自動推測的欄位型別 |
---|---|
null | 沒有欄位被新增 |
true or false | boolean |
浮點型別數字 | float |
數字 | long |
JSON物件 | object |
陣列 | 有陣列中第一個非空值決定 |
string | 有可能是date型別(開啟日企檢測),double,long,text,keyword |
動態對映json體:
{
"settings":{
"number_of_shards":3,
"number_of_replicas":1
}
}
number_of_shards是用來設定分片數量的 number_of_replicas是用來設定副本數量的 靜態對映Json體:
{
"settings":{
"number_of_shards":3,
"number_of_replicas":1
},
"mappings":{
"it": {
"dynamic":"strict",
"properties":{
"title":{
"type":"text"
},
"content":{
"type":"text"
},
"create_date":{
"type":"date"
}
}
}
}
}
這裡的it指的就是型別,在properties中新增自己的欄位,並且指定屬性的型別。
另外發送請求的content-type一定得是application/json,這個值得注意,成功後,會返回一個屬性acknowledged 是true的,就說明建立成功,其他的如下圖(Tips:幾個更換 json體,這裡的截圖只是一個示範):
檢視head外掛,如下圖
我們可以看到這裡建立了三個分片(細線為粗線的副本)。
2.插入文件
url地址 | method | 用途 |
---|---|---|
localhost:9200/索引名稱/型別名稱/文件id | put | 建立文件(指定文件id) |
localhost:9200/索引名稱/型別名稱 | post | 建立文件(隨機文件id) |
3.修改文件
url地址 | method | 用途 |
---|---|---|
localhost:9200/索引名稱/型別名稱/文件id/_update | post | 修改文件 |
json體:
{
"doc":{
"修改欄位名稱": "想要修改成的值"
}
}
4.刪除文件
url地址 | method | 用途 |
---|---|---|
localhost:9200/索引名稱/型別名稱/文件id | delete | 刪除文件 |
5.查詢文件 這裡先介紹簡單的查詢,複雜的地方,會在後面說到。
url地址 | method | 用途 |
---|---|---|
localhost:9200/索引名稱/型別名稱/文件id | get | 查詢文件通過文件id |
localhost:9200/索引名稱/型別名稱/_search | post | 查詢所有資料 |
簡單查詢資料結構體為
{
"query":{
"match_all":{},(通過該屬性查詢所有資料)
"match":{
"需要查詢的欄位名稱":"查詢的值"
}
},
"from": "從第幾個開始"(可選),
"size": "要查詢多少個"(可選) ,
"sort": [
{"欄位名稱":{"order": "desc 或者是 asc"}}(自定義排序,預設通過score元欄位進行排序)
]
}
聚合查詢結構體為: (可以定義多個聚合條件,放在不同的聚合名稱中)
{
"aggs":{
"聚合名稱1(自定義)": {
"terms":{
"field": "通過該欄位進行聚合"
},
"status":{
"field": "通過該欄位進行聚合"(status key可以計算這個聚合的相關引數)
}
},
"聚合名稱2(自定義)": {
"terms":{
"field": "通過該欄位進行聚合"
}
}
}
}
後記
這篇文章是學習了慕課網上瓦力老師的教程並參考《從lucene到Elasticsearch全文檢索實戰》所寫,課程地址為https://www.imooc.com/learn/889,在此感謝你們的分享,我會在後續的文章中繼續總結elasticsearch的更多查詢語法,以及Spring Boot 整合 Elastic Search 的相關知識。