學前導讀
- 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
pattern 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
格式
從開始紀元(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預設文字是英文,變更成中文
啟動
訪問
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"
}
}
}
}