ElasticSearch探索之路(六)实战:环境搭建、REST、CRUD、Search
文章目錄
- 環境搭建
- 搭建Elasticsearch環境
- 搭建Kibana環境
- 基本操作
- RESTful
- CRUD
- 創建索引
- 插入文檔
- 查詢文檔
- 更新文檔
- 刪除文檔和索引
- Search
- 查詢方式
- URL + 參數
- URL + QueryDSL
- match 匹配
- match 匹配查詢
- match_all 全部匹配
- match_phase 短語匹配
- multi_match 多字段匹配
- term 精確查詢
- 布爾查詢(復合查詢)
- Filter 過濾器
- Aggregations 聚合
環境搭建
搭建Elasticsearch環境
下載docker鏡像
docker pull elasticsearch:7.4.2映射配置文件
# 配置映射文件夾 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data# 設置文件夾權限任何用戶可讀可寫 chmod 777 /mydata/elasticsearch -R# 配置 http.host echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml啟動容器
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \ -e "discovery.type"="single-node" \ # 設置為單節點 -e ES_JAVA_OPTS="-Xms64m -Xmx128m" \ # 設置啟動時ES的初始內存以及最大內存 -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \ -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ -d elasticsearch:7.4.2訪問ES服務,http://127.0.0.1:9200/
得到相應體如下:
{"name" : "de85ed684243","cluster_name" : "elasticsearch","cluster_uuid" : "UeIP1PrXT2OFd7FlEEl3hQ","version" : {"number" : "7.4.2","build_flavor" : "default","build_type" : "docker","build_hash" : "2f90bbf7b93631e52bafb59b3b049cb44ec25e96","build_date" : "2019-10-28T20:40:44.881551Z","build_snapshot" : false,"lucene_version" : "8.2.0","minimum_wire_compatibility_version" : "6.8.0","minimum_index_compatibility_version" : "6.0.0-beta1"},"tagline" : "You Know, for Search" }可以通過/_cat來獲取節點信息
# 訪問http://82.157.127.173:9200/_cat# 屬性列表 /_cat/allocation /_cat/shards /_cat/shards/{index} /_cat/master /_cat/nodes /_cat/tasks /_cat/indices /_cat/indices/{index} /_cat/segments /_cat/segments/{index} /_cat/count /_cat/count/{index} /_cat/recovery /_cat/recovery/{index} /_cat/health /_cat/pending_tasks /_cat/aliases /_cat/aliases/{alias} /_cat/thread_pool /_cat/thread_pool/{thread_pools} /_cat/plugins /_cat/fielddata /_cat/fielddata/{fields} /_cat/nodeattrs /_cat/repositories /_cat/snapshots/{repository} /_cat/templates搭建Kibana環境
下載docker鏡像
docker pull kibana:7.4.2啟動容器
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.0.128:9200 -p 5601:5601 -d kibana:7.4.2訪問Kibana服務,http://127.0.0.1:5601/
基本操作
RESTful
一種軟件架構風格,而不是標準,只是提供了一組設計原則和約束條件。它主要用于客戶端和服務器交互類的軟件。基于這個風格設計的軟件可以更簡潔,更有層次,更易于實現緩存等機制。
ES的基本REST命令:
| PUT | localhost:9200/索引名稱/類型名稱/文檔id | 創建文檔(指定文檔id) |
| GET | localhost:9200/索引名稱/類型名稱/文檔id | 通過文檔id查詢文檔 |
| POST | localhost:9200/索引名稱/類型名稱 | 創建文檔(隨機文檔id) |
| POST | localhost:9200/索引名稱/類型名稱/文檔id/_update | 修改文檔 |
| POST | localhost:9200/索引名稱/類型名稱/_search | 查詢所有數據 |
| DELETE | localhost:9200/索引名稱/類型名稱/文檔id | 刪除文檔 |
CRUD
創建索引
在創建索引時,我們可以聲明字段與數據類型的映射
請求:
PUT /test0 {"mappings":{"properties":{"name":{"type":"text"},"author":{"type":"text"}}} }響應:
{"acknowledged": true,"shards_acknowledged": true,"index": "test0" }即使如果我們沒有配置類型,ES也會根據字段的內容來自行推導。
注意??:由于索引具有不變性,我們只能進行追加而不能更改已經存在的映射字段,必須創建新的索引后進行數據遷移。
POST _reindex {"source": {"index": "test0"},"dest": {"index": "test1"} }插入文檔
PUT和POST都可以插入文檔:
- POST:如果不指定 id,自動生成 id。如果指定 id,則修改這條記錄,并新增版本號。
- PUT:必須指定 id,如果沒有這條記錄,則新增,如果有,則更新。
示例:在 test1 索引下的books類型中保存標識為 1 的文檔。
請求:
PUT /test1/books/1 {"name":"three days to see","author" : "Daniel Defoe" }響應:
{"_index": "test", //索引"_type": "book", //類型"_id": "1", //id"_version": 1, //版本號"result": "updated", //操作類型"_shards": { //分片"total": 2,"successful": 1,"failed": 0},"_seq_no": 1, //并發控制字段,每次更新就會+1,用來做樂觀鎖"_primary_term": 1 //同上,主分片重新分配,如重啟,就會變化 }查詢文檔
示例:查詢test1索引下的books類型中保存標識為 1 的文檔的內容。
請求:
GET /test1/books/1響應:
{"_index": "test1","_type": "books","_id": "1","_version": 1,"_seq_no": 0,"_primary_term": 1,"found": true,"_source": {"name": "three days to see","author": "Daniel Defoe"} }更新文檔
使用POST命令,在ID后面加_update,并把需要修改的內容放入doc屬性中
示例:更新test1 索引下的books類型中保存標識為 1 的文檔的內容。
請求:
POST /test1/books/1/_update {"doc" : {"name":"three days to see","author" : "Daniel Defoe","country" : "England"} }響應:
{"_index": "test1","_type": "books","_id": "1","_version": 2,"result": "updated","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 1,"_primary_term": 1 }刪除文檔和索引
刪除使用DELETE命令
示例:刪除文檔/test1/books/1
請求:
DELETE /test1/books/1響應:
{"_index": "test1","_type": "books","_id": "1","_version": 3,"result": "deleted","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 2,"_primary_term": 1 }示例:刪除索引/test1
DELETE /test1響應:
{"acknowledged": true }Search
為了方便測試,可以從官網導入測試數據
測試數據
查詢方式
ES支持兩種查詢方式,一種是直接在URL后加上參數,另一種是在URL后加上JSON格式的請求體。
示例:查找到收入最高的十條記錄
URL + 參數
常用的參數如下
- q:用于指定搜索的關鍵詞。
- from & size:類似于SQL中的offset和limit。
- sort:對結果排序,默認為降序。
- _source:指定想要返回的屬性。
URL + QueryDSL
GET /test_data/_search {"query": {"match_all" : {} },"sort" : [{"balance" : "desc"}],"from" : 0,"size" : 10 }雖然URL+參數的寫法非常簡潔,但是隨著邏輯的復雜化,其可讀性也越來越差,所以通常都會使用URL + QueryDSL的格式。
match 匹配
match 匹配查詢
無論你在任何字段上進行的是全文搜索還是精確查詢,match 查詢是你可用的標準查詢。
對于not_analyzed的字段,match能做到精確查詢,而對于analyzed的字段,match能做到匹配查詢(全文搜索)。
示例:查找所有年齡為25歲的記錄(精確查詢)
請求:
GET /test_data/_search {"query":{"match" : {"age": 25} } }示例:查詢所有地址與976 Lawrence Street相關的記錄(全文搜索)
請求:
GET /test_data/_search {"query":{"match" : {"address": "976 Lawrence Street"} } }match_all 全部匹配
match_all 用于查詢所有文檔。在沒有指定查詢方式時,它是默認。
示例:查詢年齡最小的十條記錄
請求:
GET /test_data/_search {"query": {"match_all" : {} },"sort" : [{"age" : "asc"}],"from" : 0,"size" : 10 }match_phase 短語匹配
match_phase用于進行短語的匹配,它查詢時并不是像term一樣不進行分詞直接查詢,而是借助分析器返回的查詢詞的相對順序以及偏移量來做判斷——滿足所有查詢詞且順序完全相同的記錄才會被匹配上。
示例:地址包含502 Baycliff Terrace的記錄
請求:
GET /test_data/_search {"query":{"match_phase" : {"address": "502 Baycliff Terrace"} } }multi_match 多字段匹配
multi_match 可以在多個字段上執行相同的 match 查詢。
示例:查找city或address字段中包含Dixie或Street的記錄。
請求:
GET /test_data/_search {"query":{"multi_match":{"query":"Dixie Street","fields":["city","address"]}} }term 精確查詢
term即直接在倒排索引中查詢,也就是精確查找,不進行分詞器分析,文檔中必須包含整個搜索的詞匯。
term和match的區別:
- match是經過分析處理的,查詢詞先被文本分析器處理后再進行查詢。所以根據不同的文本分析器,分析出
的結果也會不同。
- term是不經過分析處理的,直接去倒排索引查找精確的值。
由于text字段會被文本分析器處理,所以通常全文檢索字段用match,其他非text字段(not_analyzed)匹配用term。
GET /test_data/_search {"query": {"term": {"address": "Street"}} }// 雖然文檔中存在”702 Quentin Street“,但是由于文本分析器默認會轉為小寫,無法搜到任何數據布爾查詢(復合查詢)
借助布爾查詢可以實現如SQL中(and、or、!=)等邏輯條件的判斷,并且可以合并任何其他查詢語句,包括復合語句。復合語句之間可以相互嵌套,可以表達復雜的邏輯。
- must(and):文檔必須匹配這些條件才能被包含進來。(影響相關性得分)
- must_not(not):文檔必須不匹配這些條件才能被包含進來。(不影響相關性得分)
- should(or):如果滿足這些語句中的任意語句,將增加得分 。(用于修正相關性得分)
示例:查找年齡不等于18的地址包含Street的男性,且優先展示居住在30歲以上的的記錄
請求:
GET /test_data/_search {"query":{"bool":{"must":[{"match":{"address":"Street"}},{"match":{"gender":"M"}}],"must_not":[{"match":{"age":"18"}}],"should":[{"range":{"age":{"gt":30}}}]}} }Filter 過濾器
Filter通常搭配布爾查詢一起使用,用于過濾出所有滿足Filter的記錄,不影響相關性得分。
示例:查找年齡在30~60之間的記錄
請求:
GET /test_data/_search {"query":{"bool":{"filter":[{"range":{"age":{"gte":30,"lte":60}}}]}} }Aggregations 聚合
要掌握聚合,你只需要明白兩個主要的概念:
- 桶(Buckets):滿足特定條件的文檔的集合
- 指標(Metrics):對桶內的文檔進行統計計算
翻譯成SQL的形式來理解的話:
SELECT COUNT(1),MAX(balance) FROM table GROUP BY gender;桶在概念上類似于 SQL 的分組(GROUP BY,如上面的GROUP BY gender),而指標則類似于 COUNT() 、 SUM() 、 MAX() 等統計方法,如MAX(balance)。
聚合的語法如下:
"aggregations" : {"<聚合名稱 1>" : {"<聚合類型>" : {<聚合體內容>}[,"元數據" : { [<meta_data_body>] }]?[,"aggregations" : { [<sub_aggregation>]+ }]?}["聚合名稱 2>" : { ... }]* }示例:按照性別進行分組,計算平均年齡和最高收入
請求:
GET /test_data/_search {"query":{"match_all": {}},"aggs":{"group_gender":{"terms":{"field":"gender"},"aggs":{"avg_age":{"avg":{"field":"age"}},"max_balance":{"max":{"field":"balance"}}}}},"size":0 }總結
以上是生活随笔為你收集整理的ElasticSearch探索之路(六)实战:环境搭建、REST、CRUD、Search的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ElasticSearch探索之路(五)
- 下一篇: 现代的缓存设计方案:Window-Tin