1.1 elasticsearch是什么?
- 簡稱ES,是一個開源的高擴展的分布式全文搜索引擎,它可以近乎實時的存儲、檢索數據;本身擴展性很好,可以擴展到上百台服務器,處理PB級別的數據,es使用Java開發並使用lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的RestFul API來隱藏Lucene的復雜性,從而讓全文檢索變得簡單
1.2 soar和es比較
- 當單純的對已有數據進行搜索時,soar更快
- 當實時建立索引時,soar會產生IO阻塞,查詢性能較差,es具有明顯的優勢
- 隨着數據量的增加,soar會變得越來越慢,而es沒有明顯的變化
1.3 es VS soar總結
- es基本開箱即用(解壓即可),而soar安裝稍微復雜一點點
- soar利用zookeeper進行分布式管理,而es自身帶有分布式協調管理功能
- soar支持更多格式的數據,如JSON、XML、csv,而es僅支持json格式
- soar官方提供的功能多,而es本身更注重於核心功能,高級功能多有第三方插件提供,例如圖形化界面需要kibana友好支撐
- soar查詢快,但更新索引時慢(即插入刪除慢),用於電商等查詢多的應用
- es建立索引快,即實時查詢快,多用於搜索
第二章 ES安裝
2.1 解壓即安裝
#把安裝包直接上傳到電腦,直接解壓即可
[es@ceshi opt]$ ll
total 16
drwxr-xr-x 10 es es 4096 Aug 30 14:09 es
drwxr-xr-x 8 root root 4096 Apr 8 03:26 jdk1.8.0_291
drwxr-xr-x 13 root root 4096 Aug 30 11:12 kibana-7.8.0-linux-x86_64
drwxr-xr-x 2 root root 4096 Aug 30 11:12 src
2.2 熟悉目錄
bin 啟動文件
config 配置文件
elasticsearch.yml es默認配置文件
log4j2.properties 日志配置文件
jvm.options 虛擬機相關配置
lib 相關jar包
logs 日志
modules 功能模塊
plugins 插件
2.3 啟動es
#在后台啟動
[es@ceshi bin]$ ./elasticsearch -d
#es啟動默認使用普通用戶,注意目錄權限問題
2.4 訪問測試
#es默認使用兩個端口,9200為外部訪問端口,9300是集群內部通信端口
{
"name" : "XIAOYAO",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "-J88UDSLSVqC1hxClaRG1w",
"version" : {
"number" : "7.8.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65",
"build_date" : "2020-06-14T19:35:50.234439Z",
"build_snapshot" : false,
"lucene_version" : "8.5.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
2.5 安裝es-head
#上傳安裝包到服務器,解壓
[root@ceshi src]# ls
elasticsearch-7.8.0-linux-x86_64.tar.gz elasticsearch-head-master.zip kibana-7.8.0-linux-x86_64.tar.gz
elasticsearch-analysis-ik-7.8.0.zip jdk-8u291-linux-x64.tar.gz
[root@ceshi src]# unzip elasticsearch-head-master.zip -d /opt/
#進入到安裝目錄,執行命令,需要提前安裝npm命令
[root@ceshi elasticsearch-head]# npm install
#運行es-head,在后台運行
[root@ceshi elasticsearch-head]# nohup npm run start &
#訪問端口9100
2.6 解決跨域問題
#此時通過es-head直接連接es,會無法連接,需要解決下跨域問題;編輯es配置文件,在后面添加參數
http.cors.enabled: true
http.cors.allow-origin: "*"
2.7 訪問測試
#重啟es,重新訪問9100端口
2.8 安裝kibana
-
kibana是一個針對elasticsearch的開源分析及可視化平台,用來搜索、查看交互存儲在Elasticsearch索引中的數據,使用kibana可以通過圖標進行高級數據分析及展示。
#上傳軟件包並解壓 [root@ceshi kibana]# cd /opt/ [root@ceshi opt]# ll total 20 drwxr-xr-x 8 root root 4096 Aug 30 14:40 elasticsearch-head drwxr-xr-x 10 es es 4096 Aug 30 14:09 es drwxr-xr-x 8 root root 4096 Apr 8 03:26 jdk1.8.0_291 drwxr-xr-x 13 root root 4096 Aug 30 14:44 kibana drwxr-xr-x 2 root root 4096 Aug 30 11:12 src
#修改配置文件 [root@ceshi config]# vi kibana.yml server.host: "172.19.70.210" elasticsearch.hosts: ["http://172.19.70.210:9200"] i18n.locale: "zh-CN" #啟動服務,使用普通帳戶啟動 [es@ceshi es]$ cd ../kibana/bin/ [es@ceshi bin]$ ./kibana
第三章 初步查詢
3.1 _cat
-
查看所有節點
GET /_cat/nodes
-
查看es健康狀況
GET /_cat/health
-
查看主節點
GET /_cat/master
-
查看所有索引
GET /_cat/indices
3.2 索引一個文檔
#保存一個數據,保存在哪個索引的哪個類型下,指定用哪一個唯一標識
#在xiaoyao索引下的test類型的保存1號數據為:
PUT xiaoyao/test/1
{
"name":"xiaoyao"
}
#輸出信息:
{
"_index" : "xiaoyao", #在哪個索引
"_type" : "test", #在哪個類型
"_id" : "1", #文檔id
"_version" : 2, #版本號
"result" : "updated", #狀態
"_shards" : { #集群分片信息
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
#PUT和POST都可以,PUT可以新增,可以修改,PUT必須指定id,由於指定id的原因,所以我們一般做修改操作,不指定id會報錯;
#POST新增,如果不指定id,會自動生成id,指定id會修改這個數據,並新增版本號
3.3 查詢文檔
GET xiaoyao/test/1
{
"_index" : "xiaoyao", #在哪個索引
"_type" : "test", #在哪個類型
"_id" : "1", #文檔id
"_version" : 2, #版本號
"_seq_no" : 1, #並發控制手段,每次更新都會加1,用來做樂觀鎖
"_primary_term" : 1, #同上,主分片重新分配。如重啟就會變化,需要結合使用
"found" : true,
"_source" : { #真正的內容
"name" : "xiaoyao"
}
}
###測試樂觀鎖,打開兩個窗口指定seq_no,第一條數據新增后,seq_no會自增,另外一個會報錯409
PUT xiaoyao/test/1?if_seq_no=1&if_primary_term=1
3.4 更新文檔
#PUT和POST都可以更新文檔,PUT更多的是對原文檔覆蓋,常用POST請求加上_update可以對某一個字段進行更新
POST xiaoyao/test/1/_update
{
"doc": {
"name":"xiaoyao"
}
}
#POST操作帶_updata會對比源文件 ,如果相同不會有任何操作,文檔version不增加,需要帶上“doc”參數
#POST不帶_updata和PUT請求效果一樣,會把源數據覆蓋。
3.5 刪除文檔&索引
#es可以對文檔和索引進行刪除操作,無法刪除類型
#刪除文檔
DELETE xiaoyao/test/1
#刪除索引
DELETE xiaoyao
3.6 bulk批量API
#只能使用post請求
POST /xiaoyao/test/_bulk
{"index": {"_id":"1"}}
{"name": "xiaoyao"}
{"index": {"_id":"2"}}
{"name": "feng"}
#語法格式
{"action":{metadata}}
{request body}
{"action":{metadata}}
{request body}
#復雜實例
POST /_bulk
{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title": "My first blog post"}
{"index": {"_index":"website","_type":"blog"}}
#bulk API以此按順序執行所有的action,如果一個單個的動作因任何原因而失敗,它將繼續處理它后面剩余的工作,當bulk API返回時,它將提供每個動作的狀態(與發送的順序相同),所以您可以檢查是否一個指定的動作是不是失敗了
3.7 樣本測試數據
#准備es樣本數據
#下載鏈接
https://gitee.com/runewbie/learning/raw/master/ElasticSearch/resource/accounts.json#
POST bank/account/_bulk
測試數據
第四章 進階查詢
4.1 SearchAPI
-
ES支持兩種基本方式檢索
-
官網查詢網址:https://www.elastic.co/guide/en/elasticsearch/reference/7.8/getting-started-search.html
-
一種是通過使用REST requestAPI發送搜索參數(uri+搜索參數)
GET /bank/_search?q=*&sort=account_number:asc #查找process索引下的所有數據以account_number字段進行升序排序,找到的數據都存放在hits命中記錄中,默認只返回10條記錄
-
另一個是通過使用REST request body來發送請求(uri+請求體)
#經常使用這種查詢方式 GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] }
-
4.2 Query DSL
4.2.1 基本語法格式
-
Elasticsearch提供了一個可以執行查詢的json風格的DSL,這個被稱為Query DSL。該查詢語音非常全面
#一個查詢語句的典型結構 { QUERY_NAME:{ ARGUMENT:VALUE } } #示例 GET /bank/_search { "query": { "match_all": {} } } #如果是針對某個字段,那么它的結構如下: { QUERY_NAME:{ FIELD_NAME:{ ARGUMENT:VALUE } } } #示例 GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": { "order": "desc" } } ] } #分頁查詢 GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": { "order": "desc" } } ], "from": 0, #從哪里開始 "size": 5 #查詢幾條數據 }
4.2.2 返回部分字段
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}
GET /bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": {
"order": "desc"
}
}
],
"from": 10,
"size": 5,
"_source": ["balance","firstname"]
}
#使用_source可以指定只返回某些字段
4.2.3 match匹配查詢
#基本類型(非字符串),精確匹配
GET bank/_search
{
"query": {
"match": {
"address": "mill lane" #字段值會進行分詞匹配
}
}
}
#查找address字段值為mill lane;支持精確查詢和模糊查詢
#全文檢索會按照評分進行排序,會對檢索條件進行分詞匹配
4.2.4 match_phrase短語匹配
#將需要匹配的值當成一個整體單詞(不分詞)進行檢索
GET bank/_search
{
"query": {
"match_phrase": {
"address": "mill lane" #字段值不會分詞匹配
}
}
}
4.2.5 multi_match多字段匹配
#state字段或者address字段內容包含mill內容,字段內容會進行分詞處理
GET bank/_search
{
"query": {
"multi_match": {
"query": "mill",
"fields": ["state","address"]
}
}
}
4.2.6 bool復合查詢
GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "ID" } }
]
}
}
}
GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"gender": "M"
}},
{"match": {
"address": "Mill"
}}
],
"must_not": [
{"match": {
"age": "18"
}}
],
"should": [
{"match": {
"lastname": "wallace"
}}
]
}
}
}
#must和must_not查詢結果必須同時滿足,should條件不滿足也能匹配,如果should條件也滿足的話,得分最高
4.2.7 filter結果過濾
#並不是所有的查詢都需要產生分數,特別是那些僅用於“filtering”(過濾)的文檔,為了不計算分數,es會自動檢查場景並且優化查詢的執行
GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": {
"address": "mill"
}}
],
"filter": [
{"range": {
"age": {
"gte": 20,
"lte": 32
}
}}
]
}
}
}
#filter可以對上面條件輸出的結果進行過濾,並且不計算分數
4.2.8 term
#和match一樣,匹配某個屬性的值,全文檢索字段用match,其他非text字段匹配用term
GET bank/_search
{
"query": {
"match": {
"age": "28"
}
}
}
GET bank/_search
{
"query": {
"term": {
"age": "28"
}
}
}
#查詢字段值為非文本格式時,兩種查詢方法都可以;字段值為文本時,term無法使用
#精確匹配
GET bank/_search
{
"query": {
"match_phrase": {
"address": "789 Madison Street"
}
}
}
#精確匹配
GET process/_search
{
"query": {
"match": {
"address.keyword": "789 Madison Street" #整個字段值的內容是全部,多或少都無法匹配
}
}
}
4.2.9 aggregations執行聚合
- 聚合提供了從數據中分組和提取數據的能力,最簡單的聚合方法大致等於SQL GROUP BY和SQL聚合函數,在elasticsearch中,你有執行搜索返回hits(命中結果),並且同時返回聚合結果,把一個響應中的所有hits(命中結果)分隔開的能力,這是非常強大且有效的,你可以執行查詢和多個聚合,並且在一次使用中得到各自的返回結果,使用一次簡潔和簡化API來避免網絡回返
#搜索address中包含mill的所有人的年齡分布以及平均年齡,但不顯示這些人的詳情
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"age_agg": {
"terms": {
"field": "age",
"size": 10
}
},
"age_avg":{
"avg": {
"field": "age"
}
},
"balanceavg": {
"avg": {
"field": "balance"
}
}
}
}
#size: 0 不顯示搜索數據,只顯示聚合結果
aggs:執行聚合,聚合語法如下
"aggs":{
"aggs_name":{ #這次聚合的名字,可自定義
"agg_type":{ #可選聚合的類型(avg、term、terms)
"field": "需要聚合的字段名"
}
}
}
---------------------------------------------------------------------------
#按照年齡聚合,並且請求這些年齡段的這些人的平均薪資
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"ageAvg": {
"avg": {
"field": "balance"
}
}
}
}
},
"size": 0
}
-------------------------------------------------------------------------
#查出所有年齡分布,並且這些年齡段中的M的平均薪資和F的平均薪資,以及這個年齡段的總體平均薪資
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"genderagg": {
"terms": {
"field": "gender.keyword",
"size": 10
},
"aggs": {
"balanceAgg": {
"avg": {
"field": "balance"
}
}
}
},
"ageBalanceAgg": {
"avg": {
"field": "balance"
}
}
}
}
}
}
#聚合text類型時,需要指定keyword
4.3 Mapping
4.3.1 字段類型
- 核心類型
- 字符串(string)
- text
- keyword
- 數字類型(number)
- long
- integer
- short
- byte
- double
- float
- half_float
- scaled_float
- 日期類型(date)
- date
- 布爾類型(Boolean)
- boolean
- 二進制類型(Binary)
- binary
- 字符串(string)
- 復合類型
- 數組類型(Array)
- Array支持不針對特定的類型
- 對象類型(Object)
- object用於單json對象
- 嵌套類型(Nested)
- nested用於json對象數組
- 數組類型(Array)
- 地理類型
- 地理坐標()
- geo_point用於描述經緯度坐標
- 地理圖形
- geo_shape用於描述復雜形狀,如多邊形
- 地理坐標()
- 特定類型
- IP類型
- ip用於描述ipv4和ipv6特征
- 補全類型
- completion提供自動完成提示
- 令牌計數類型
- token_count用於統計字符串中的詞條數量
- 附件類型
- 參考mapper-attachements插件,支持將附件如Microsoft Office格式,Open Document格式,epub,HTML等等索引為attachment數據類型
- 抽取類型
- 接受特定領域查詢語言(query-dsl)的查詢
- IP類型
4.3.2 映射
-
mapping用來定義一個文檔,以及它所包含的屬性是如何存儲和索引的,比如使用mapping來定義
-
- elasticsearch是基於lucene開發的搜索引擎,而es中不同type下名稱相同的filed最終在lucene中的處理方式是一樣的
- 兩個不同type下的兩個user_name,在es同一個索引下其實被認為是同一個filed,你必須在兩個不同的type中定義相同的filed映射,否則,不同type中的相同字段名稱就會在處理中出現沖突的情況,導致lucene處理性能下降
- 去掉type就是為了提高es處理數據的效率
- es7.x版本中的type參數可選,比如索引一個文檔不再要求提供文檔類型,es8.x中不再支持type參數
4.3.3 新版本改變
-
查看索引mapping信息
GET bank/_mapping
-
創建索引,並指定映射關系
PUT /my_index { "mappings": { "properties": { "age":{"type": "integer"}, "email":{"type": "keyword"}, "name":{"type": "text"} } } }
-
添加新的字段映射
PUT /my_index/_mapping { "properties": { "employee-id" :{ "type":"keyword", "index":"false" #默認所有的字段都能夠被索引,如果配置false,則不能被檢索 } } }
-
查看特定字段映射
GET /my_index/_mapping/field/employee-id
-
更新映射
- 對於已經存在的映射字段,我們不能更新,更新必須創建新的索引進行數據遷移
-
數據遷移
- 把之前老銀行的數據轉移到新索引
#先創建一個新的索引,並指定正確的字段映射關系 PUT /newbank { "mappings": { "properties": { "account_number": { "type": "long" }, "address": { "type": "keyword" }, "age": { "type": "integer" }, "balance": { "type": "long" }, "city": { "type": "keyword" }, "email": { "type": "keyword" }, "employer": { "type": "text" }, "firstname": { "type": "text" }, "gender": { "type": "keyword" }, "lastname": { "type": "text" }, "state": { "type": "keyword" } } } }
數據轉移
POST _reindex
{
"source": {
"index": "bank"
}
, "dest": {
"index": "newbank"
}
}
4.4 IK分詞器
- 把一段中文或者別的划分成一個個的關鍵字,我們在搜索時候會把自己信息進行分詞,會把數據庫中或者索引中的數據進行分詞,然后再進行一個匹配操作,默認的中文分詞是將每個字看成一個詞,比如“我愛中國”會被分成“我”,“愛”,"中","國",這顯然是不符合要求的,所以我們需要安裝中文分詞器ik來解決這個問題
- ik提供了兩個分詞算法:ik_smart和ik_max_word,其中ik_smart為最少切分,ik_max_word為最細粒度划分
#上傳軟件包並解壓文件到es的插件目錄中
[root@ceshi src]# ls
elasticsearch-7.8.0-linux-x86_64.tar.gz elasticsearch-head-master.zip kibana-7.8.0-linux-x86_64.tar.gz
elasticsearch-analysis-ik-7.8.0.zip jdk-8u291-linux-x64.tar.gz
[root@ceshi src]# unzip elasticsearch-analysis-ik-7.8.0.zip -d /opt/es/plugins/ik/
#重啟es進程,並查看安裝的插件
[es@ceshi bin]$ ./elasticsearch-plugin list
future versions of Elasticsearch will require Java 11; your Java version from [/opt/jdk1.8.0_291/jre] does not meet this requirement
ik
-
自己需要的詞,需要自己加到我們的分詞器字典中
#創建一個my.dic文件,在字典中添加 <!--用戶可以在這里配置自己的擴展字典 --> <entry key="ext_dict">my.dic</entry> #my.dic是我們自己創建的字典,以后的話,我們需要自己配置分詞就在自己定義的dic文件中進行配置即可!