ElasticSearch 7.8.1 從入門到精通
學前導讀
- ElasticSearch對電腦配置要求較高,記憶體至少4G以上,空閒2G記憶體,執行緒數4018+
- 學習的時候,推薦將ElasticSearch安裝到Linux或者mac上,極度不推薦裝Windows上(坑太多,伺服器部署的時候,也不會部署到Window上,學習用Windows上玩,不是耽誤自個時間麼)。如果是Window使用者想學這個,電腦自身至少16G,然後裝虛擬機器,在虛擬機器上搞個Linux玩
- Linux系統不建議裝6/6.5版本的(啟動的時候,會檢查核心是否3.5+,當然可以忽略這個檢查),推薦裝7+
- 自身電腦配置不高的話,怎麼辦呢?土豪做法,去買個雲伺服器叭,在雲伺服器上玩
注意事項
上面第1、2點未滿足,又捨不得去買雲伺服器的小夥伴,就不要往下面看了,看了也白看,ElasticSearch對電腦配置要求較高,前置條件未滿足的話,服務是起不來的。
演示環境說明
我演示的時候,是用的mac系統,上面裝了個虛擬機器,虛擬機器版本Centos6.5,jdk用的13,ElasticSearch用的版本是 7.8.1。這些我使用的包我下面也會提供,為了學習的話,儘量和我使用的版本一致,這樣大家碰到的問題都一樣,安裝過程中,我也猜了不少坑,都總結出來了,仔細閱讀文件就可以搗鼓出來。
什麼是搜尋引擎?
常用的搜尋網站:百度、谷歌
資料的分類
結構化資料
指具有固定格式或有限長度的資料,如資料庫,元資料等。對於結構化資料,我們一般都是可以通過關係型資料庫(mysql、oracle)的table的方法儲存和搜尋,也可以建立索引。通過b-tree等資料結構快速搜尋資料
非結構化資料
全文資料,指不定長或無固定格式的資料,如郵件,word等。對於非結構化資料,也即對全文資料的搜尋主要有兩種方式:順序掃描法,全文搜尋法
順序掃描法
我們可以瞭解它的大概搜尋方式,就是按照順序掃描的方式查詢特定的關鍵字。比如讓你在一篇籃球新聞中,找出“科比”這個名字在那些段落出現過。那你肯定需要從頭到尾把文章閱讀一遍,然後標出關鍵字在哪些地方出現過
這種方式毋庸置疑是最低效的,如果文章很長,有幾萬字,等你閱讀完這篇新聞找到“科比”這個關鍵字,那得花多少時間
全文搜尋
對非結構化資料進行順序掃描很慢,我們是否可以進行優化?把非結構化資料想辦法弄得有一定結構不就好了嘛?將非結構化資料中的一部分資訊提取出來,重新組織,使其變得有一定結構,然後對這些有一定結構的資料進行搜尋,從而達到搜尋相對較快的目的。這種方式就構成了全文搜尋的基本思路。這部分從非結構化資料提取出的然後重新組織的資訊,就是索引。
什麼是全文搜尋引擎
根據百度百科中的定義,全文搜尋引擎是目前廣泛應用的主流搜尋引擎。它的工作原理是計算機索引程式通過掃描文章中的每個詞,對每個詞建立一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程式就根據事先建立的索引進行查詢,並將查詢的結果反饋給使用者。
常見的搜尋引擎
Lucene
- Lucene是一個Java全文搜尋引擎,完全用Java編寫。lucene不是一個完整的應用程式,而是一個程式碼庫和API,可以很容易地用於嚮應用程式新增搜尋功能
- 通過簡單的API提供強大的功能
- 可擴充套件的高效能索引
- 強大,準確,高效的搜尋演算法
- 跨平臺解決方案
- Apache軟體基金會
- 在Apache軟體基金會提供的開源軟體專案的Apache社群的支援
- 但是Lucene只是一個框架,要充分利用它的功能,需要使用Java,並且在程式中整合Lucene。需要很多的學習瞭解,才能明白它是如何執行的,熟練運用Lucene確實非常複雜
Solr
- Solr是一個基於Lucene的Java庫構建的開源搜尋平臺。它以友好的方式提供Apache Lucene的搜尋功能。它是一個成熟的產品,擁有強大而廣泛的使用者社群。它能提供分散式索引,複製,負載均衡以及自動故障轉移和恢復。如果它被正確部署然後管理的好,他就能夠成為一個高可用,可擴充套件且容錯的搜尋引擎
- 強大功能
- 全文搜尋
- 突出
- 分面搜尋
- 實時索引
- 動態叢集
- 資料庫整合
- NoSQL功能和豐富的文件處理
ElasticSearch
- ElasticSearch是一個開源,是一個機遇Apache Lucene庫構建的Restful搜尋引擎
- ElasticSearch是Solr之後幾年推出的。它提供了一個分散式,多租戶能力的全文搜尋引擎,具有HTTP Web頁面和無架構JSON文件。ElasticSearch的官方客戶端提供Java、Php、Ruby、Perl、Python、.Net和JavaScript
- 主要功能
- 分散式搜尋
- 資料分析
- 分組和聚合
- 應用場景
- 維基百科
- Stack Overflow
- GitHub
- 電商網站
- 日誌資料分析
- 商品價格監控網站
- BI系統
- 站內搜尋
- 籃球論壇
搜尋引擎的快速搭建
環境準備
注意,我使用的linux搭建的,當然Window(極度不推薦,坑太多)也能搭建,ElasticSearch安裝前需要先安裝jdk,這裡我使用的是jdk13,因為linux自帶jdk版本,需要先將之前的jdk版本解除安裝(點我直達),在安裝指定的jdk版本!!!
開發環境,建議關閉防火牆,避免不必要的麻煩!!!!生產環境,視情況開啟埠號!!!!
service iptables stop 命令關閉防火牆,但是系統重啟後會開啟 chkconfig iptables off--關閉防火牆開機自啟動
「注意事項」
ElasticSearch是強依賴jdk環境的,所以一定要安裝對應的jdk版本,並配置好相關的環境變數,比如ES7.X版本要裝jdk8以上的版本,而且是要官方來源的jdk。啟動的時候有可能會提示要裝jdk11,因為ES7以上官方都是建議使用jdk11,但是一般只是提示資訊,不影響啟動。
ES官網推薦JDK版本相容地址:點我直達
ES強依賴JVM,也很吃記憶體,所以一定要保證你的機器至少空閒出2G以上記憶體。推薦使用Linux,可以本地搭建虛擬機器。
啟動一定要使用非root賬戶!!!!這是ES強制規定的。ElasticSearch為了安全考慮,不讓使用root啟動,解決辦法是新建一個使用者,用此使用者進行相關的操作。如果你用root啟動,會報錯。如果是使用root賬戶安裝ES,首先給安裝包授權,比如chown -R 777 安裝包路徑。然後再使用非root賬戶啟動,具體的許可權配置,根據自己想要的配置。
補充
高版本的ElasticSearch自帶jdk版本的,Linux中我安裝的是jdk13,沒用ElasticSearch自帶的jdk,有興趣的小夥伴可以去研究下。
下載
官網地址:點我直達
我使用的包(推薦和我版本保持一致)
連結: https://pan.baidu.com/s/1jjNEErHtBu93HmvxKCT5Sw 密碼: kbcs
修改配置檔案
1、修改elasticsearch-x.x.x/config/elasticsearch.yml,主要修改成以下內容
cluster.name: my-application node.name: node-1 network.host: 0.0.0.0 http.port: 9200 discovery.seed_hosts: ["127.0.0.1", "[::1]"] cluster.initial_master_nodes: ["node-1"] bootstrap.system_call_filter: false http.cors.allow-origin: "*" http.cors.enabled: true http.cors.allow-headers : X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization http.cors.allow-credentials: true
2、來到elasticsearch-x.x.x/bin下,執行:sh elasticsearch啟動,報錯,修改配置檔案elasticsearch-env
3、設定使用者和組
groupadd elsearch #新增使用者組,語法:groupadd 組名 useradd elsearch -g elsearch -p elasticsearch #新增使用者,並將使用者新增到組中,語法:useradd 使用者名稱 -p 密碼 -g 組名 chown -R elsearch:elsearch elasticsearch-6.3.0 # 給使用者組授權,語法:chown -R 使用者:組名 es安裝完整路徑
注意=================以上root使用者操作===============
注意=================以下es使用者操作================
注意:若es使用者密碼登入不上,在回到root使用者下,修改es使用者的密碼,語法:passwd 要修改使用者名稱
4、登入到es使用者下,繼續啟動ElasticSearch,執行:sh elasticsearch
報錯如下: java.lang.UnsupportedOperationException: seccomp unavailable: requires kernel 3.5+ with CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER compiled in 原因:我用的Centos6.5,其linux核心版本為2.6。而Elasticsearch的外掛要求至少3.5以上版本。 解決方案:禁用這個外掛即可 修改elasticsearch.yml檔案,在最下面新增如下配置: bootstrap.system_call_filter: false
5.繼續啟動ElasticSearch,執行:sh elasticsearch
修改一下內容需要使用root許可權
報錯如下4條: [1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535] [2]: max number of threads [1024] for user [es] is too low, increase to at least [4096] [3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] [4]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured ==========分割線=============== 解決辦法如下 1、vim /etc/security/limits.conf檔案,新增 * soft nofile 65535 * hard nofile 65535 2、vim /etc/security/limits.conf檔案,新增 * soft nproc 4096 * hard nproc 4096 3、vim /etc/sysctl.conf 檔案,新增 vm.max_map_count=262144 4、vim /var/soft/es7.8.1/elasticsearch-7.8.1/config/elasticsearch.yml 檔案,新增 cluster.initial_master_nodes: ["node-1"]
修改完之後,一定要重啟,重啟,重啟,重要的事兒說三遍!!!!!
上面第2條問題,執行緒數修改不了,可以嘗試使用這個方法修改執行緒數
Elasticsearch7.8.1 [1]: max number of threads [1024] for user [es] is too low, increase to at least [4096]異常 根據linux系統差異,有時候需要來點終極解決方案 新建: /etc/security/limits.d/test-limits.conf cat>>test-limits.conf 然後加下內容: * soft nofile 65535 * hard nofile 65535 * soft nproc 4096 * hard nproc 4096 ctrl+d儲存即可; 然後重啟伺服器即可;
配置小結
1、第一次配置過程中,踩了不少坑,我踩過的坑,都在上面記錄了
2、如果照我上面哪個方法還解決不了,自行根據ElasticSearch日誌,百度去找答案叭····
啟動
正常啟動
進入軟體的安裝目錄,進入到bin 執行:sh elasticsearch
守護進行啟動
進入軟體的安裝目錄,進入到bin 執行:sh elasticsearch -d -p pid
驗證
開啟瀏覽器輸入:127.0.0.1:9200
ElasticSearch目錄結構介紹
型別 | 描述 | 預設位置 | 設定 |
bin | ⼆進位制指令碼包含啟動節點的elasticsearch | {path.home}/bin | |
conf | 配置⽂件包含elasticsearch.yml | {path.home}/confifig | path.conf |
data | 在節點上申請的每個index/shard的資料⽂件的位置。 可容納多個位置 | {path.home}/data | path.data |
logs | ⽇志⽂件位置 | {path.home}/logs | path.logs |
plugins | 外掛⽂件位置。每個外掛將包含在⼀個⼦⽬錄中。 | {path.home}/plugins | path.plugins |
ElasticSearch快速入門
核心概念
前言
傳統資料庫查詢資料的操作步驟是這樣的:建立資料庫->建表->插入資料->查詢
索引(index)
一個索引可以理解成一個關係型資料庫
型別(type)
一個type就像一類表,比如user表、order表
注意
1、ES 5.X中一個index可以有多種type
2、ES 6.X中一個index只能有一種type
3、ES 7.X以後已經移除type這個概念
對映(mapping)
mapping定義了每個欄位的型別等資訊。相當於關係型資料庫中的表結構
文件(document)
一個document相當於關係型資料庫中的一行記錄
欄位(field)
相當於關係型資料庫表的欄位
叢集(cluster)
叢集由一個或多個節點組成,一個叢集由一個預設名稱“elasticsearch”
節點(node)
叢集的節點,一臺機器或者一個程序
分片和副本(shard)
- 副本是分片的副本。分片有主分片(primary Shard)和副本分片(replica Shard)之分
- 一個Index資料在屋裡上被分佈在多個主分片中,每個主分片只存放部分資料
- 每個主分片可以有多個副本,叫副本分片,是主分片的複製
RESTful風格的介紹
介紹
- RESTful是一種架構的規範與約束、原則,符合這種規範的架構就是RESTful架構
- 先看REST是什麼意思,英文Representational state transfer表述性狀態轉移,其實就是對資源的標書性狀態轉移,即通過HTTP動詞來實現資源的狀態扭轉
- 資源是REST系統的核心概念。所有的設計都是以資源為中心
- elasticsearch使用RESTful風格api來設計的
方法
action | 描述 |
HEAD | 只獲取某個資源的頭部資訊 |
GET | 獲取資源 |
POST | 建立或更新資源 |
PUT | 建立或更新資源 |
DELETE | 刪除資源 |
GET /user:列出所有的⽤戶 POST /user:新建⼀個⽤戶 PUT /user:更新某個指定⽤戶的資訊 DELETE /user/ID:刪除指定⽤戶
除錯工具
Postman工具(推薦)
curl工具
獲取elasticcsearch狀態
curl -X GET "http://localhost:9200"
新建一個文件
curl -X PUT "localhost:9200/xdclass/_doc/1" -H 'Content-Type: application/json' -d' { "user" : "louis", "message" : "louis is good" }
刪除一個文件
curl -X DELETE "localhost:9200/xdclass/_doc/1"
索引的使用
新增
單個獲取
批量獲取
刪除
獲取所有
方式一
方式二
判斷索引是否存在(存在,返回200,不存在404)
關閉索引
此時再次查詢cba時,返回json會多一行
開啟索引
關閉索引標記消失
對映的使用
介紹
定義索引的結構,之前定義一個nba索引,但是沒有定義他的結構,我們現在開始建立mapping;
type="keyword":是一個關鍵字,不會被分詞
type="text":會被分詞,使用的是全文索引
新增
json格式
{ "properties": { "name": { "type": "text" }, "team_name": { "type": "text" }, "position": { "type": "keyword" }, "play_year": { "type": "keyword" }, "jerse_no": { "type": "keyword" } } }
獲取
批量獲取
獲取所有mapping
方式一
方式二
新增一次欄位
文件的操作
新增
不指定索引方式新增
踩坑(要POST請求)
PUT請求改POST
自動建立索引
- 檢視auto_create_index開關狀態,請求:http://ip:port/_cluster/settings
- 當索引不存在並且auto_create_index為true的時候,新增文件時會自動建立索引
- 修改auto_create_index狀態
- put方式:ip:port/_cluster/settings
{ "persistent": { "action.auto_create_index": "false" } }
當auto_create_index=false時,指定一個不存在的索引,新增文件
{ "name":"楊超越", "team_name":"夢之隊", "position":"組織後衛", "play_year":"0", "jerse_no":"18" }
指定操作型別
PUT請求:ip:port/xxx/_doc/1?op_type=create
文件檢視
檢視多個文件
方式一
{ "docs": [{ "_index": "nba", "_type": "_doc", "_id": "1" }, { "_index": "nba", "_type": "_doc", "_id": "2" } ] }
方式二
方式三
方式四
修改
向_source欄位,增加一個欄位
{ "script": "ctx._source.age = 18" }
從source欄位,刪除一個欄位
{ "script": "ctx._source.remove(\"age\")" }
根據引數值,更新指定文件的欄位
upsert當指定的文件不存在時,upsert引數包含的內容將會被插入到索引中,作為一個新文件;如果指定的文件存在,ElasticSearch引擎將會執行指定的更新邏輯。
刪除文件
搜尋的簡單使用
準備工作
刪除nba索引
新建一個索引
並指定mapping
{ "mappings": { "properties": { "name": { "type": "text" }, "team_name": { "type": "text" }, "position": { "type": "text" }, "play_year": { "type": "long" }, "jerse_no": { "type": "keyword" } } } }
新增document
192.168.199.170:9200/nba/_doc/1 { "name": "哈登", "team_name": "⽕箭", "position": "得分後衛", "play_year": 10, "jerse_no": "13" }
192.168.199.170:9200/nba/_doc/2 { "name": "庫⾥", "team_name": "勇⼠", "position": "控球后衛", "play_year": 10, "jerse_no": "30" }
192.168.199.170:9200/nba/_doc/3 { "name": "詹姆斯", "team_name": "湖⼈", "position": "⼩前鋒", "play_year": 15, "jerse_no": "23" }
詞條查詢(term)
詞條查詢不會分析查詢條件,只有當詞條和查詢字串完全匹配時,才匹配搜尋。
單挑term查詢
{ "query": { "term": { "jerse_no": "23" } } }
多條term查詢
{ "query": { "terms": { "jerse_no": [ "23", "13" ] } } }
全文查詢(full text)
ElasticSearch引擎會先分析查詢字串,將其拆分成多個分詞,只要已分析的欄位中包含詞條的任意一個,或全部包含,就匹配查詢條件,返回該文件;如果不包含任意一個分詞,表示沒有任何問的那個匹配查詢條件
match_all
{ "query": { "match_all": {} }, "from": 0, "size": 10 }
match
{ "query": { "match": { "position":"後衛" } }, "from": 0, "size": 10 }
multi_match
{ "query": { "multi_match": { "query": "shooter", "fields": ["title", "name"] } } }
post 192.168.199.170:9200/nba/_update/2 { "doc": { "name": "庫⾥", "team_name": "勇⼠", "position": "控球后衛", "play_year": 10, "jerse_no": "30", "title": "the best shooter" } }
match_phrase
類似於詞條查詢,精準查詢
match_phrase_prefix
字首匹配
{ "query": { "match_phrase_prefix": { "title": "the best s" } } }
post 192.168.199.170:9200/nba/_update/3 { "doc": { "name": "詹姆斯", "team_name": "湖⼈", "position": "⼩前鋒", "play_year": 15, "jerse_no": "23", "title": "the best small forward" } }
分詞器的介紹和使用
什麼是分詞器
- 將使用者輸入的一段文字,按照一定邏輯,分析成多個詞語的一種工具
- example:The best 3-points shooter is Curry!
常用的內建分詞器
- standard analyzer
- simple analyzer
- whitespace analyzer
- stop analyzer
- language analyzer
- pattern analyzer
standard analyzer
標準分析器是預設分詞器,如果未指定,則使用該分詞器
{ "analyzer": "standard", "text": "The best 3-points shooter is Curry!" }
simple analyzer
simple分析器當他遇到只要不是字母的字元,就將文字解析成term,而且所有的term都是小寫的
whitespace analyzer
whitespace分析器,當他遇到空白字元時,就將文字解析成terms
stop analyzer
stop分析器和simple分析器很想,唯一不同的是,stop分析器增加了對刪除停止詞的支援,預設使用了english停止詞
stopwords預定義的停止詞列表,比如(ths,a,an,this,of,at)等等
language analyzer
(特定的語⾔的分詞器,⽐如說,english,英語分詞器),內建語⾔:arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english, fifinnish, french, galician, german, greek, hindi, hungarian, indonesian, irish, italian, latvian, lithuanian, norwegian, persian, portuguese, romanian, russian, sorani, spanish, swedish, turkish, thaipattern analyzer
用正則表示式將文字分割成sterms,預設的正則表示式是\W+
選擇分詞器
put 192.168.199.170:9200/my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "whitespace" } } } }, "mappings": { "properties": { "name": { "type": "text" }, "team_name": { "type": "text" }, "position": { "type": "text" }, "play_year": { "type": "long" }, "jerse_no": { "type": "keyword" }, "title": { "type": "text", "analyzer": "my_analyzer" } } } }
{ "name": "庫⾥", "team_name": "勇⼠", "position": "控球后衛", "play_year": 10, "jerse_no": "30", "title": "The best 3-points shooter is Curry!" }
{ "query": { "match": { "title": "Curry!" } } }
常見中文分詞器
預設的分詞standard
{ "analyzer": "standard", "text": "⽕箭明年總冠軍" }
常見分詞器
- smartCN一個簡單的中文或中英文混合文字的分詞器
- IK分詞器,更智慧更友好的中文分詞器
安裝smartCN
- sh elasticsearch-plugin install analysis-smartcn
校驗
安裝後重啟
{ "analyzer": "smartcn", "text": "⽕箭明年總冠軍" }
解除安裝
sh elasticsearch-plugin remove analysis-smartcn
IK分詞器
下載地址:點我直達
安裝,解壓到plugins目錄
然後重啟
常見的欄位型別
資料型別
- 核心資料型別
- 複雜資料型別
- 專用資料型別
核心資料型別
字串
- text:用於全文索引,該型別的欄位將通過分詞器進行分詞
- keyword:不分詞,只能搜尋該欄位的完整的值
數值型
- long、integer、short、byte、double、float、half_float、scaled_float
布林
- boolean
二進位制
- binary:該型別的欄位把值當做經過base64編碼的字串,預設不儲存,且不可搜尋
範圍型別
- 範圍型別表示值是一個範圍,而不是一個具體的值
- integer_range、float_range、long_range、double_range、date_range
- 比如age型別是integer_range,那麼值可以是{"gte":20,"lte":40};搜尋"term":{"age":21}可以搜尋該值
日期-date
由於json型別沒有date型別,所以es通過識別字符串是否符合format定義的格式來判斷是否為date型別
format預設為:strict_date_optional_time || epoch_millis
格式
"2022-01-01" "2022/01/01 12:10:30" 這種字串格式從開始紀元(1970年1月1日0點)開始的毫秒數
PUT 192.168.199.170:9200/nba/_mapping { "properties": { "name": { "type": "text" }, "team_name": { "type": "text" }, "position": { "type": "text" }, "play_year": { "type": "long" }, "jerse_no": { "type": "keyword" }, "title": { "type": "text" }, "date": { "type": "date" } } }
POST 192.168.199.170:9200/nba/_doc/4 { "name": "蔡x坤", "team_name": "勇⼠", "position": "得分後衛", "play_year": 10, "jerse_no": "31", "title": "打球最帥的明星", "date": "2020-01-01" }
POST 192.168.199.170:9200/nba/_doc/5 { "name": "楊超越", "team_name": "猴急", "position": "得分後衛", "play_year": 10, "jerse_no": "32", "title": "打球最可愛的明星", "date": 1610350870 }
POST 192.168.199.170:9200/nba/_doc/6 { "name": "吳亦凡", "team_name": "湖⼈", "position": "得分後衛", "play_year": 10, "jerse_no": "33", "title": "最會說唱的明星", "date": 1641886870000 }
複雜資料型別
資料型別 Array
- ES中沒有專門的資料型別,直接使用[]定義介面,陣列中所有的值必須是同一種資料型別,不支援混合資料型別的陣列
- 字串陣列["one","two"]
- 整數陣列[1,2]
- Object物件陣列[{"name":"alex","age":18},{"name":"tom","age":18}]
物件型別Object
POST 192.168.199.170:9200/nba/_doc/8 { "name": "吳亦凡", "team_name": "湖⼈", "position": "得分後衛", "play_year": 10, "jerse_no": "33", "title": "最會說唱的明星", "date": "1641886870", "array": [ "one", "two" ], "address": { "region": "China", "location": { "province": "GuangDong", "city": "GuangZhou" } } }
索引方式
"address.region": "China", "address.location.province": "GuangDong", "address.location.city": "GuangZhou"
POST 192.168.199.170:9200/nba/_search { "query": { "match": { "address.region": "china" } } }
專用資料型別
IP型別
IP型別的欄位用於儲存IPv4和IPv6的地址,本質上是一個長整形欄位
POST 192.168.199.170:9200/nba/_mapping { "properties": { "name": { "type": "text" }, "team_name": { "type": "text" }, "position": { "type": "text" }, "play_year": { "type": "long" }, "jerse_no": { "type": "keyword" }, "title": { "type": "text" }, "date": { "type": "date" }, "ip_addr": { "type": "ip" } } }
PUT 192.168.199.170:9200/nba/_doc/9 { "name": "吳亦凡", "team_name": "湖⼈", "position": "得分後衛", "play_year": 10, "jerse_no": "33", "title": "最會說唱的明星", "ip_addr": "192.168.1.1" }
POST 192.168.199.170:9200/nba/_search { "query": { "term": { "ip_addr": "192.168.0.0/16" } } }
kibana工具的安裝和使用
簡介
視覺化工具kibana的安裝和使用
下載
點我直達
賦許可權
chown -R es:es781g /var/soft/kibana-7.8.1-linux-x86_64 # 給使用者組授權,語法:chown -R 使用者:組名 es安裝完整路徑
kibana.yml
server.port: 5601 #kibana埠 server.host: "10.0.0.169" #繫結的主機IP地址 elasticsearch.hosts: ["http://10.0.0.169:9200"] #elasticsearch的主機IP kibana.index: ".kibana" #開啟此選項 i18n.locale: "zh-CN" #kibana預設文字是英文,變更成中文
啟動
進⼊到⽂件夾的bin⽬錄,執⾏sh kibana訪問
ip:5601
簡單使用
後面示例,會大量使用該工具
ES之批量匯入資料
簡介
手把手教你批量匯入資料
Bulk
ES提供了一個叫bulk的API來進行批量操作
批量匯入
資料
{"index": {"_index": "book", "_type": "_doc", "_id": 1}} {"name": "權⼒的遊戲"} {"index": {"_index": "book", "_type": "_doc", "_id": 2}} {"name": "瘋狂的⽯頭"}
POST bulk
curl -X POST "192.168.199.170:9200/_bulk" -H 'Content-Type: application/json' --data-binary @test
ES之term的多種查詢
介紹
- 單詞級別查詢
- 這些查詢通常用於結構化的資料,比如:number,data,keyword等,而不是對text
- 也就是說,全文查詢之前要先對文字內容進行分詞,而單詞級別的查詢直接在相應欄位的反向索引中精確查詢,單詞級別的查詢一般用於數值、日期等型別的欄位上
準備工作
- 刪除nba
- 新增nba索引
{"mappings":{"properties":{"birthDay":{"type":"date"},"birthDayStr": {"type":"keyword"},"age":{"type":"integer"},"code": {"type":"text"},"country":{"type":"text"},"countryEn": {"type":"text"},"displayAffiliation":{"type":"text"},"displayName": {"type":"text"},"displayNameEn":{"type":"text"},"draft": {"type":"long"},"heightValue":{"type":"float"},"jerseyNo": {"type":"text"},"playYear":{"type":"long"},"playerId": {"type":"keyword"},"position":{"type":"text"},"schoolType": {"type":"text"},"teamCity":{"type":"text"},"teamCityEn": {"type":"text"},"teamConference": {"type":"keyword"},"teamConferenceEn":{"type":"keyword"},"teamName": {"type":"keyword"},"teamNameEn":{"type":"keyword"},"weight": {"type":"text"}}}}
- 批量匯入player
Term query精準匹配查詢
POST nba/_search { "query": { "term": { "jerseyNo": "23" } }, "from": 0, "size": 20 }
Exsit Query在特定的欄位中查詢非空值的文件(查詢隊名非空的球員)
Prefix Query查詢包含帶有指定字首term的文件(查詢隊名為Rock開頭的球員)
Wildcard Query支援萬用字元查詢,*表示任意字元,?表示任意單個字元(查詢火箭隊的球員)
Regexp Query正則表示式查詢(查詢火箭隊的球員)
Ids Query(查詢id為1和2的球員)
ES的範圍查詢
查詢指定欄位在指定範圍內包含值(日期、數字或字串)的文件
查詢在nba打球在2年到10年以內的球員
POST nba/_search { "query": { "range": { "playYear": { "gte": 2, "lte": 10 } } }, "from": 0, "size": 20 }
查詢1999年到2020年出生的球員
POST nba/_search { "query": { "range": { "birthDay": { "gte": "01/01/1999", "lte": "2020", "format": "dd/MM/yyyy||yyyy" } } }, "from": 0, "size": 20 }
ES的布林查詢
布林查詢
type | description |
must | 必須出現在匹配文件中 |
filter | 必須出現在文件中,但是不打分 |
must_not | 不能出現在文件中 |
should | 應該出現在文件中 |
must(查詢名字叫做james的球員)
POST nba/_search { "query": { "bool": { "must": [ { "match": { "displayNameEn": "james" } } ] } }, "from": 0, "size": 20 }
效果通must,但是不打分(查詢名字叫做james的球員)
POST nba/_search { "query": { "bool": { "filter": [ { "match": { "displayNameEn": "james" } } ] } }, "from": 0, "size": 20 }
must_not(查詢名字叫做James的西部球員)
POST nba/_search { "query": { "bool": { "must": [ { "match": { "displayNameEn": "james" } } ], "must_not": [ { "term": { "teamConferenceEn": { "value": "Eastern" } } } ] } }, "from": 0, "size": 20 }
組合起來含義:一定不在東部的james
should(查詢名字叫做James的打球時間應該在11到20年西部球員)
即使匹配不到也返回,只是評分不同
POST nba/_search { "query": { "bool": { "must": [ { "match": { "displayNameEn": "james" } } ], "must_not": [ { "term": { "teamConferenceEn": { "value": "Eastern" } } } ], "should": [ { "range": { "playYear": { "gte": 11, "lte": 20 } } } ] } }, "from": 0, "size": 20 }
如果minimum_should_match=1,則變成要查出名字叫做James的打球時間在11年到20年西部球員
POST nba/_search { "query": { "bool": { "must": [ { "match": { "displayNameEn": "james" } } ], "must_not": [ { "term": { "teamConferenceEn": { "value": "Eastern" } } } ], "should": [ { "range": { "playYear": { "gte": 11, "lte": 20 } } } ], "minimum_should_match": 1 } }, "from": 0, "size": 20 }
minimum_should_match代表了最小匹配經度,如果設定minimum_should_match=1,那麼should語句中至少需要有一個條件滿足
ES的排序
火箭隊中按打球時間從大到小排序的球員
POST nba/_search { "query": { "match": { "teamNameEn": "Rockets" } }, "sort": [ { "playYear": { "order": "desc" } } ], "from": 0, "size": 20 }
火箭隊中按打球時間從大到小,如果年齡相同則按照身高從高到低排序的球員
POST nba/_search { "query": { "match": { "teamNameEn": "Rockets" } }, "sort": [ { "playYear": { "order": "desc" } },{ "heightValue": { "order": "asc" } } ], "from": 0, "size": 20 }
ES聚合查詢之指標聚合
ES聚合查詢是什麼
- 聚合查詢是資料庫中重要的功能特性,完成對一個查詢得到的資料集的聚合計算,如:找出某欄位(或計算表示式的結果)的最大值,最小值,計算和,平均值等。ES作為搜尋引擎,同樣提供了強大的聚合分析能力
- 對一個數據集求最大、最小、和、平均值等指標的聚合,在ES中稱為指標聚合
- 而關係型資料庫中除了有聚合函式外,還可以對查詢出的資料進行分組group by,再在組上進行指標聚合。在ES中稱為“桶聚合”
max min sum avg
求出火箭隊球員的平均年齡
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "avgAge": { "avg": { "field": "age" } } }, "size": 0 }
value_count統計非空欄位的文件數
求出火箭隊中球員打球時間不為空的數量
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "countPlayerYear": { "value_count": { "field": "playYear" } } }, "size": 0 }
查出火箭隊有多少名球員
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } } }
Cardinality值去重計數
查出火箭隊中年齡不同的數量
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "countAget": { "cardinality": { "field": "age" } } }, "size": 0 }
stats統計count max min avg sum5個值
查出火箭隊球員的年齡stats
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "statsAge": { "stats": { "field": "age" } } }, "size": 0 }
Extended stats比stats多4個統計結果:平方和、方差、標準差、平均值加/減兩個標準差的區間
查詢火箭隊球員的年齡Extend stats
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "extendStatsAge": { "extended_stats": { "field": "age" } } }, "size": 0 }
Percentiles佔比百分位對應的值統計,預設返回【1,5,25,50,75,95,99】分位上的值
查出火箭的球員的年齡佔比
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "pecentAge": { "percentiles": { "field": "age" } } }, "size": 0 }
查出火箭的球員的年齡佔比(指定分位值)
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "pecentAge": { "percentiles": { "field": "age", "percents": [ 20, 50, 75 ] } } }, "size": 0 }
ES聚合查詢之桶聚合
ES聚合分析是什麼
- 聚合分析是資料庫中重要的功能特性,完成對一個查詢的資料集中資料的聚合計算,如:找出欄位(或計算表示式的結果)的最大值、最小值、計算和、平均值等。ES作為搜尋引擎相容資料庫,同樣提供了強大的聚合分析能力
- 對一個數據集求最大、最小、和、平均值等指標的聚合,在ES中稱為指標聚合
- 而關係型資料庫中除了有聚合函式外,還可以對查詢出的資料進行分組group by,再在組上進行遊標聚合。在ES中稱為桶聚合
Terms Aggregation根據欄位項分組聚合
火箭隊根據年齡進行分組
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "aggsAge": { "terms": { "field": "age", "size": 10 } } }, "size": 0 }
Order分組聚合排序
火箭隊根據年齡進行分組,分組資訊通過年齡從大到小排序(通過指定欄位)
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "aggsAge": { "terms": { "field": "age", "size": 10, "order": { "_key": "desc" } } } }, "size": 0 }
火箭隊根據年齡進行分組,分組資訊通過文件數從大到小排序(通過文件數)
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "aggsAge": { "terms": { "field": "age", "size": 10, "order": { "_count": "desc" } } } }, "size": 0 }
每支球隊按該隊所有球員的平均年齡進行分組排序(通過分組指標值)
POST /nba/_search { "query": { "term": { "teamNameEn": { "value": "Rockets" } } }, "aggs": { "avgAge": { "avg": { "field": "age" } } }, "size": 0 }
篩選分組聚合
湖人和火箭隊按球隊平均年齡進行分組排序(指定值列表)
POST /nba/_search { "aggs": { "aggsTeamName": { "terms": { "field": "teamNameEn", "include": [ "Lakers", "Rockets", "Warriors" ], "exclude": [ "Warriors" ], "size": 30, "order": { "avgAge": "desc" } }, "aggs": { "avgAge": { "avg": { "field": "age" } } } } }, "size": 0 }
湖人和火箭隊按球隊平均年齡進行分組排序(正則表示式匹配值)
POST /nba/_search { "aggs": { "aggsTeamName": { "terms": { "field": "teamNameEn", "include": "Lakers|Ro.*|Warriors.*", "exclude": "Warriors", "size": 30, "order": { "avgAge": "desc" } }, "aggs": { "avgAge": { "avg": { "field": "age" } } } } }, "size": 0 }
Range Aggregation範圍分組聚合
NBA球員年齡按20,20-35,35這樣分組
POST /nba/_search { "aggs": { "ageRange": { "range": { "field": "age", "ranges": [ { "to": 20 }, { "from": 20, "to": 35 }, { "to": 35 } ] } } }, "size": 0 }
NBA球員年齡按20,20-35,35這樣分組(起別名)
Date Range Aggregation時間範圍分組聚合
NBA球員按出生年月分組
POST /nba/_search { "aggs": { "birthDayRange": { "date_range": { "field": "birthDay", "format": "MM-yyy", "ranges": [ { "to": "01-1989" }, { "from": "01-1989", "to": "01-1999" }, { "from": "01-1999", "to": "01-2009" }, { "from": "01-2009" } ] } } }, "size": 0 }
Date Histogram Aggregation時間柱狀圖聚合
按天、月、年等進行聚合統計。可按year(1y),quarter(1q),month(1M),week(1w),day(1d),hour(1h),minute(1m),second(1s)間隔聚合
NBA球員按出生年分組
POST /nba/_search { "aggs": { "birthday_aggs": { "date_histogram": { "field": "birthDay", "format": "yyyy", "interval": "year" } } }, "size": 0 }
ES之query_string查詢
簡介
query_string查詢,如果熟悉lucene的查詢語法,我們可以直接用lucene查詢語法寫一個查詢串進行查詢,ES中接到請求後,通過查詢解析器,解析查詢串生成對應的查詢。
指定單個欄位查詢
POST /nba/_search { "query": { "query_string": { "default_field": "displayNameEn", "query": "james OR curry" } }, "size": 100 }
POST /nba/_search { "query": { "query_string": { "default_field": "displayNameEn", "query": "james AND harden" } }, "size": 100 }
指定多個欄位查詢
ElasticSearch的高階使用
別名有什麼用
在開發中,隨著業務需求的迭代,較老的業務邏輯就要面臨更新甚至是重構,而對於es來說,為了適應新的業務邏輯,可能就要對原有的索引做一些修改,比如對某欄位做調整,甚至是重構索引。而做這些操作的時候,可能會對業務造成影響,甚至是停機調整等問題。由此,es提供了索引別名來解決這些問題。索引別名就像一個快捷方式或軟連線,可以指向一個或多個索引,也可以給任意一個需要索引名的API來使用。別名的應用為程式提供了極大地靈活性。
查詢別名
GET /nba/_alias GET /_alias
新增別名
POST /_aliases { "actions": [ { "add": { "index": "nba", "alias": "nba_v1.0" } } ] }
刪除別名
方式一 POST /_aliases { "actions": [ { "remove": { "index": "nba", "alias": "nba_v1.0" } } ] } 方式二 DELETE /nba/_alias/nba_v1.0
重新命名別名
POST /_aliases { "actions": [ { "remove": { "index": "nba", "alias": "nba_v1.0" } }, { "add": { "index": "nba", "alias": "nba_v2.0" } } ] }
為多個索引指定一個別名
POST /_aliases { "actions": [ { "add": { "index": "nba", "alias": "nba_v2.0" } },{ "add": { "index": "cba", "alias": "cba_v2.0" } } ] }
為同個索引指定多個別名
POST /_aliases { "actions": [ { "add": { "index": "nba", "alias": "nba_v2.0" } },{ "add": { "index": "nba", "alias": "cba_v2.2" } } ] }
通過別名讀索引
當別名指定了一個索引,則查出一個索引
當別名指定了多個索引,則查出多個索引
GET /nba_v2.2
通過別名寫索引
當別名指定了一個索引,則可以做寫的操作
POST /nba_v2.0/_doc/566 { "countryEn": "Croatia", "teamName": "快船", "birthDay": 858661200000, "country": "克羅埃西亞", "teamCityEn": "LA", "code": "ivica_zubac", "displayAffiliation": "Croatia", "displayName": "伊維察 祖巴茨哥哥", "schoolType": "", "teamConference": "⻄部", "teamConferenceEn": "Western", "weight": "108.9 公⽄", "teamCity": "洛杉磯", "playYear": 3, "jerseyNo": "40", "teamNameEn": "Clippers", "draft": 2016, "displayNameEn": "Ivica Zubac", "heightValue": 2.16, "birthDayStr": "1997-03-18", "position": "中鋒", "age": 22, "playerId": "1627826" }
當別名指定了多個索引,可以指定寫某個索引
POST /_aliases { "actions": [ { "add": { "index": "nba", "alias": "national_player", "is_write_index": true } }, { "add": { "index": "cba", "alias": "national_player" } } ] }
POST /national_player/_doc/566 { "countryEn": "Croatia", "teamName": "快船", "birthDay": 858661200000, "country": "克羅埃西亞", "teamCityEn": "LA", "code": "ivica_zubac", "displayAffiliation": "Croatia", "displayName": "伊維察 祖巴茨妹妹", "schoolType": "", "teamConference": "⻄部", "teamConferenceEn": "Western", "weight": "108.9 公⽄", "teamCity": "洛杉磯", "playYear": 3, "jerseyNo": "40", "teamNameEn": "Clippers", "draft": 2016, "displayNameEn": "Ivica Zubac", "heightValue": 2.16, "birthDayStr": "1997-03-18", "position": "中鋒", "age": 22, "playerId": "1627826" }
ES之重建索引
簡介
ElasticSearch是一個實時的分散式搜尋引擎,為使用者提供搜尋服務,當我們決定儲存某種資料時,在建立索引的時候需要將資料結構完整確定下來,於此同時索引的設定和很多固定配置將不能修改。當需要改變資料結構時,就需要重新建立索引,為此,Elastic團隊提供了很多輔助工具幫助開發人員進行重建索引
步驟
- nba取一個別名nba_latest,nba_latest作為對外使用
- 新增一個索引nba_20200810,結構複製於nba索引,根據業務要求修改欄位
- 將nba資料同步至nba_20200810
- 給nba_20200810新增別名nba_latest,刪除此處nba別名nba_latest
- 刪除nba索引
PUT /nba_20220810 { "mappings": { "properties": { "age": { "type": "integer" }, "birthDay": { "type": "date" }, "birthDayStr": { "type": "keyword" }, "code": { "type": "text" }, "country": { "type": "keyword" }, "countryEn": { "type": "keyword" }, "displayAffiliation": { "type": "text" }, "displayName": { "type": "text" }, "displayNameEn": { "type": "text" }, "draft": { "type": "long" }, "heightValue": { "type": "float" }, "jerseyNo": { "type": "keyword" }, "playYear": { "type": "long" }, "playerId": { "type": "keyword" }, "position": { "type": "text" }, "schoolType": { "type": "text" }, "teamCity": { "type": "text" }, "teamCityEn": { "type": "text" }, "teamConference": { "type": "keyword" }, "teamConferenceEn": { "type": "keyword" }, "teamName": { "type": "keyword" }, "teamNameEn": { "type": "keyword" }, "weight": { "type": "text" } } } }
將舊索引資料copy到新索引
同步等待,介面將會在reindex結束後返回
POST /_reindex { "source": { "index": "nba" }, "dest": { "index": "nba_20220810" } }
非同步執行,如果reindex時間過長,建議加上“wait_for_completion=false”的引數條件,這樣reindex將直接返回taskId
POST /_reindex?wait_for_completion=false { "source": { "index": "nba" }, "dest": { "index": "nba_20220810" } }
替換別名
POST /_aliases { "actions": [ { "add": { "index": "nba_20220810", "alias": "nba_latest" } }, { "remove": { "index": "nba", "alias": "nba_latest" } } ] }
刪除舊索引
DELETE /nba
通過別名訪問新索引
POST /nba_latest/_search { "query": { "match": { "displayNameEn": "james" } } }
ES之refresh操作
理想的搜尋
新的資料一新增到索引中立馬就能搜尋到,但是真實情況不是這樣的
我們使用鏈式命令請求,先新增一個文件,再立刻搜尋
curl -X PUT 192.168.199.170:9200/star/_doc/888 -H 'Content-Type: application/json' -d '{ "displayName": "蔡徐坤" }' curl -X GET localhost:9200/star/_doc/_search?pretty
強制重新整理
curl -X PUT 192.168.199.170:9200/star/_doc/666?refresh -H 'Content-Type: application/json' -d '{ "displayName": "楊超越" }' curl -X GET localhost:9200/star/_doc/_search?pretty
修改預設更新時間(預設時間是1s)
PUT /star/_settings { "index": { "refresh_interval": "5s" } }
將refresh關閉
PUT /star/_settings { "index": { "refresh_interval": "-1" } }
ES之高亮查詢
前言
如果返回的結果集中很多符合條件的結果,那怎麼能一眼就能看到我們想要的那個結果呢?比如下面網站所示的那樣,我們搜尋“科比”,在結果集中,將所有“科比”高亮顯示?
高亮查詢
POST /nba_latest/_search { "query": { "match": { "displayNameEn": "james" } }, "highlight": { "fields": { "displayNameEn": {} } } }
自定義高亮查詢
POST /nba_latest/_search { "query": { "match": { "displayNameEn": "james" } }, "highlight": { "fields": { "displayNameEn": { "pre_tags": [ "<h1>" ], "post_tags": [ "</h1>" ] } } } }
ES之查詢建議
查詢建議是什麼
查詢建議:是為了給使用者提供更好的搜尋體驗。包括:詞條檢查,自動補全
詞條檢查
自動補全
Suggester
- Term suggester
- Phrase suggester
- Completion suggester
欄位
text | 指定搜尋文字 |
field | 獲取建議詞的搜尋欄位 |
analyzer | 指定分詞器 |
size | 每個詞返回的最大建議詞數 |
sort |
如何對建議詞進行排序,可用選項: score:先按評分排序、再按文件頻率排、term順序 frequency:先按文件頻率排,再按評分,term順序排 |
suggest_mode |
建議模式,控制提供建議詞的方式: missing:僅在搜尋的詞項在索引中不存在時才提供建議詞,預設值; popular:僅建議文件頻率比搜尋詞項高的詞 always:總是提供匹配的建議詞 |
Term Suggester
term詞條建議器,對給輸入的文字進行分詞,為每個分詞提供詞項建議
POST /nba_latest/_search { "suggest": { "my-suggestion": { "text": "jamse hardne", "term": { "suggest_mode": "missing", "field": "displayNameEn" } } } }
Phrase suggester
phrase短語建議,在term的基礎上,會考量多個term之間的關係,比如是否同時出現在索引的原文裡,相鄰成都,以及詞頻等
POST /nba_latest/_search { "suggest": { "my-suggestion": { "text": "jamse harden", "phrase": { "field": "displayNameEn" } } } }
Completion suggester
Completion完成建議
POST /nba_latest/_search { "suggest": { "my-suggestion": { "text": "Miam", "completion": { "field": "teamCityEn" } } } }