ElasticSearch 入門
本篇為 ElasticSearch 入門學習總結(jié)筆記,課程視頻地址:ElasticSearch 入門
一、ElasticSearch 簡介
1.1、什么是ElasticSearch
? 簡稱 ES
- 基于Apache Lucene 構(gòu)建的 開源搜索引擎,提供一個分布式多用戶能力的全文搜索引擎
- 采用 JAVA 編寫的 ,提供簡單易用的 RESTFul API(RESTFul web接口),當前流行的企業(yè)級搜索引擎
- 輕松的 橫向擴展,可支持PB級 的結(jié)構(gòu)化或非結(jié)構(gòu)化數(shù)據(jù)處理
- 可以準實時地快速存儲、搜索、分析海量的數(shù)據(jù)。(用于云計算中,能夠達到實時搜索)
1.2、應用場景
- 海量數(shù)據(jù)分析引擎(聚合搜索)
- 站內(nèi)搜索引擎
- 數(shù)據(jù)倉庫
1.3、誰在用ES呢?
英國衛(wèi)報— 實時分析公眾對文章的回應
維基百科、GitHub - 站內(nèi)實時搜索
百度—實時日志監(jiān)控平臺
阿里、Google、小米、京東....
1.4、環(huán)境要求
| 工具 | 版本 |
|---|---|
| IDE | IDEA或Eclipse |
| JAVA | JDK8 |
| Maven | 3.x 以上 |
| NodeJS | 6.0以上 |
二、ElasticSearch 安裝
2.1、ES版本問題
- 版本歷史 : 1.x-》2.x-》5.x -》最新6.0
- 版本選擇 : 選擇6.0進行演練!
2.2、ES安裝-單實例
下載地址:ES Downloads,windows環(huán)境下載 ZIP sha ,Linux或者Mac環(huán)境下,下載TAR sha。
windows 下安裝elasticsearch(有訪問頁面)
ElasticSearch安裝部署(Windows)(添加到windows)
2.2.1 單實例的安裝(Windows)
1、下載ES zip包
2、安裝Jdk8,并查看環(huán)境變量配置
3、解壓ES包
- 目錄說明:
| 目錄名 | 說明 |
|---|---|
| config | 配置文件 |
| modules | 模塊存放目錄 |
| bin | 腳本 |
| lib | 第三方庫 |
| plugins | 第三方插件 |
4、啟動驗證服務
? windows環(huán)境在/bin 下載雙擊 elasticsearch.bat 。啟動成功,看到starting....最后是started!
[2018-08-18T22:18:41,578][INFO ][o.e.n.Node ] [-Jy0w6-] starting ...
[2018-08-18T22:18:44,044][INFO ][o.e.t.TransportService ] [-Jy0w6-] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}, {[::1]:9300}
{ml.machine_memory=8441524224, xpack.installed=true, ml.max_open_jobs=20, ml.enabled=true}, reason: apply cluster state (from master [master {-Jy0w6-}{-Jy0w6-QTKquaudbtTAQMQ}
[2018-08-18T22:18:48,923][INFO ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [-Jy0w6-] publish_address {127.0.0.1:9200}, bound_addresses {127.0.0.1:9200}, {[::1]:9200}
[2018-08-18T22:18:48,924][INFO ][o.e.n.Node ] [-Jy0w6-] started
? 然后訪問 http://localhost:9200/ ,頁面響應json格式數(shù)據(jù),服務啟動正常!

2.2.2 實用插件Head安裝(Windows)
ES 默認返回的信息在頁面上是Json格式顯示!不太友好!
Head插件的優(yōu)點:
- 提供了友好的web界面,解決數(shù)據(jù)在界面顯示問題
- 實現(xiàn)基本信息的查看和Restful 請求的模擬以及數(shù)據(jù)的基本檢索
1、安裝Head的步驟
? 1)、安裝Node 6.x以上J環(huán)境,安裝 執(zhí)行指令npm install -g grunt -cli進行安裝grunt。
? 2)、 下載elasticsearch-head包,在Github【elasticsearch-head】上面,直接選擇下載的DownLoad zip到本地!
? 3)、保存在 F:\elasticsearch_learn\ 文件夾下面并對 elasticsearch-head 進行解壓!
? 4)、在 F:\elasticsearch_learn\elasticsearch-head-master文件夾目錄下面,使用 npm install !
F:\elasticsearch_learn\elasticsearch-head-master>npm install
注意:第一次==執(zhí)行失敗了!==報了下面的錯誤(可能是網(wǎng)絡不好的原因,網(wǎng)絡好的時候在嘗試執(zhí)行一次),但是服務啟動沒有問題!
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0
npm ERR! node v6.10.3
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! phantomjs-prebuilt@2.1.16 install: `node install.js`
npm ERR! Exit status 1
....
npm ERR! Please include the following file with any support request:
npm ERR! F:\elasticsearch_learn\elasticsearch-head-master\npm-debug.log
? 5)、doc窗口 在 F:\elasticsearch_learn\elasticsearch-head-master文件夾目錄下面執(zhí)行
# npm run start 或者 grunt server
F:\elasticsearch_learn\elasticsearch-head-master>npm run start
? 6)、驗證服務,默認訪問地址http://localhost:9100,如下圖顯示:

2、修改相應的配置
ElasticSearch和 elasticsearch-head 本質(zhì)上是兩個服務進程,訪問存在跨域問題,需要進行一些設置。
在 elasticsearch安裝目錄 /config/elasticsearch.yml ,在這個配置文件的末尾追加下面兩行配置信息并保存!
http.cors.enabled: true
http.cors.allow-origin: "*"
| 屬性 | 缺省值 | 描述 |
|---|---|---|
| http.cors.enabled | true | 如果啟用了 HTTP 端口,那么此屬性會指定是否允許跨源 REST 請求。 |
| http.cors.allowed.origin | localhost | 如果 http.cors.enabled 的值為 true,那么該屬性會指定允許 REST 請求來自何處。 |
更多屬性配置,請查看 【Elasticsearch 服務配置屬性】
3、驗證elasticsearch和 elasticsearch-head
- 啟動 elasticsearch服務
- 啟動elasticsearch-head 服務
訪問 http://localhost:9100 地址!查看elasticsearch 集群健康值是否正常!正常如下圖:
==注: 集群健康值==
red(差):集群 健康狀況很差,雖然可以查詢,但是已經(jīng)出現(xiàn)了丟失數(shù)據(jù)的現(xiàn)象 ;
yellow(中):集群健康狀況不是很好,但是集群可以正常使用 ;
green(優(yōu)):集群健康狀況良好,集群正常使用。

2.3、ES安裝-分布式安裝
1)、安裝說明,安裝三個節(jié)點,一個master ,兩個slave。
| 集群名稱 | ip-端口 |
|---|---|
| myEsCluster (master) | 127.0.0.1:9500 |
| myEsCluster(slave) | 127.0.0.1:9600 |
| myEsCluster(slave) | 127.0.0.1:9700 |
2)、Es安裝包解壓出三份ES,修改每個 elasticsearch安裝目錄 /config/elasticsearch.yml 這個配置文件
master配置說明:
# 設置支持elasticsearch-head
http.cors.enabled: true
http.cors.allow-origin: "*"
# 設置集群master配置信息
# 首先要指定 集群的名字 ,名字隨便起,符合常規(guī)命名規(guī)則
cluster.name: myEsCluster
# 節(jié)點的名字,一般為master 或者 slave
node.name: master
# 節(jié)點是否為master,設置為true的話,說明此節(jié)點為master節(jié)點
node.master: true
# 設置網(wǎng)絡,如果是本機的話就是127.0.0.1,其他服務器配置對應的IP地址即可
network.host: 127.0.0.1
# 默認端口為 9200,可以修改默認設置
http.port: 9500
slave配置說明:
# 設置集群slave配置信息
# 首先要指定 集群的名字 ,名字隨便起,符合常規(guī)命名規(guī)則
cluster.name: myEsCluster
# 節(jié)點的名字,一般為master 或者 slave
node.name: slave1
# 節(jié)點是否為master,設置為true的話,說明此節(jié)點為master節(jié)點
node.master: false
# 默認端口為 9200,可以修改默認設置
http.port: 9600
# 設置網(wǎng)絡,如果是本機的話就是127.0.0.1,其他服務器配置對應的IP地址即可
network.host: 127.0.0.1
# 設置集群中master節(jié)點的初始列表,可以通過這些節(jié)點來自動發(fā)現(xiàn)新加入集群的節(jié)點??梢允且粋€數(shù)組。
# #discovery.zen.ping.unicast.hosts: ["host1", "host2"]
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
==兩個slave配置只需要改相應的端口號即可!一個slave1:9600 ,一個slave2:9700。==
更多配置參考:
3)、配置后完成后,啟動master的,然后啟動Slave,也啟動elasticsearch-head服務,此時頁面可以查看Es集群的狀態(tài)!如下圖所示:

2.4、 總結(jié)
從上面的安裝來看,Es的安裝相對還是比較簡單,并且在安裝分布式的時候,通過簡單的配置就可以快速擴展多個ES節(jié)點,能夠快速的進行擴容,非常靈活,方便!
三、ElasticSearch 基礎概念
3.1、基本概念
集群和節(jié)點
集群:是由一個或者多個ES節(jié)點組成的集合。 每一個集群都有一個唯一的名字,默認是ElasticSearch。每個節(jié)點也都有唯一名字。

索引
索引: 含有相同屬性的文檔集合,比如產(chǎn)品的索引,用戶的索引等
類型:索引可以定義一個或多個類型,文檔必須屬于一個類型(一般會定義有相同字段的文檔為一個類型)
文檔:文檔是可以被所有的基本數(shù)據(jù)單位,是整個ES中最小的存儲單位
==索引在Es中是通過一個名字來識別的,而且它的名字必須是 英文字母小寫,且不能有中劃線。==
都是通過這個名字來進行增刪查改。
| ES | 數(shù)據(jù)庫 |
|---|---|
| 索引 | 實例database |
| 類型 | 表-table |
| 文檔 | 一行記錄 |
舉例:圖書索引 ---> 文學類型、技能類型...---->每一本書可以看成一個文檔
分片和備份
分片: 每個索引都有多個分片,每個分片是一個Lucene索引
? 分片的好處:假如數(shù)據(jù)量很大的話,就會造成硬盤的壓力很大,同時搜索速度也會出現(xiàn)瓶頸,將索引分成多個分片,從而分攤壓力提供效率。
備份:拷貝一份分片就完成了分片的備份,提供可用性
ES默認在創(chuàng)建索引的時候,會創(chuàng)建5個分片,1個備份。這個默認的數(shù)量是可以修改的。
? number_of_shards: 每個索引的主分片數(shù),默認值是 5 。這個配置在索引創(chuàng)建后不能修改。
? number_of_replicas:每個主分片的副本數(shù),默認值是 1 。對于活動的索引庫,這個配置可以隨時修改。
==注意==:索引的分片只能在創(chuàng)建索引的時候指定,而不能再后期進行修改。備份是可以動態(tài)修改的。
四、ElasticSearch 基本用法
ES是以Restful API的風格來命名的。
-
API 的基本格式
http://<ip>:<port>/<索引>/<類型>/<文檔id>
-
常用HTTP動詞
GET/PUT/POST/DELETE
4.1、索引的創(chuàng)建
問題:如何確定一個索引是非結(jié)構(gòu)化還是結(jié)構(gòu)的化的呢?
結(jié)合Head插件,索引-->索引信息,查看JSON數(shù)據(jù)中mappings,如果數(shù)據(jù)為空,則說明是非結(jié)構(gòu)化索引。
非結(jié)構(gòu)化創(chuàng)建
使用Head插件進行索引的創(chuàng)建,在tab標簽上,選擇索引,點 新建索引,輸入索引的名稱,注意名稱的命名規(guī)則。(我自己驗證,中文、有中劃線的索引名字都可以創(chuàng)建成功!但是字母必須是小寫?。?/p>
創(chuàng)建成功每個框框,都是Es索引的分片,粗線框是主分片 和 細線框 是分片的備份。

結(jié)構(gòu)化創(chuàng)建
1)、使用Head插件進行索引的創(chuàng)建,在tab標簽上,選擇復合查詢,進行如下配置:

2)、或者使用PostMan工具進行索引的創(chuàng)建
說明:
在Elasticsearch 6.0.0或更高版本中創(chuàng)建的索引只包含一個mapping type。 在5.x中使用multiple mapping types創(chuàng)建的索引將繼續(xù)像以前一樣在Elasticsearch 6.x中運行。 Mapping types將在Elasticsearch 7.0.0中完全刪除。
Indices created in Elasticsearch 6.0.0 or later may only contain a single mapping type. Indices created in 5.x with multiple mapping types will continue to function as before in Elasticsearch 6.x. Mapping types will be completely removed in Elasticsearch 7.0.0.
PUT 127.0.0.1:9500/people
請求參數(shù):
{
"settings":{
"number_of_shards":3,
"number_of_replicas":1
},
"mappings":{
"man":{
"properties":{
"name":{
"type":"text"
},
"age":{
"type":"integer"
},
"birth":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"country":{
"type":"keyword"
}
}
},
"woman":{}
}
}

結(jié)果:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "people"
}
如果一個mappings中有兩個type的話,在提交的時候會報如下錯誤:
PUT 127.0.0.1:9500/people2
參數(shù):
{
"settings":{
"number_of_shards":3,
"number_of_replicas":1
},
"mappings":{
"man":{
"properties":{
"name":{
"type":"text"
},
"age":{
"type":"integer"
},
"birth":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"country":{
"type":"keyword"
}
}
},
"woman":{}
}
}
結(jié)果:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Rejecting mapping update to [people2] as the final mapping would have more than 1 type: [woman, man]"
}
],
"type": "illegal_argument_exception",
"reason": "Rejecting mapping update to [people2] as the final mapping would have more than 1 type: [woman, man]"
},
"status": 400
}
4.2、插入
文檔ID是一個唯一索引值,指向我們的文檔數(shù)據(jù)。
指定文檔ID插入
PUT 127.0.0.1:9500/people/man/1
指定插入文檔的ID為 1.
參數(shù):
{
"name":"dufy",
"age":27,
"birth":"1992-09-28",
"country":"China"
}
請求結(jié)果:
{
"_index": "people",
"_type": "man",
"_id": "1", # id 為1
"_version": 1,
"result": "created", # 標識創(chuàng)建一個文檔
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
使用Head插件查看數(shù)據(jù):

自動產(chǎn)生文檔ID插入
自動產(chǎn)生ID和上面指定ID插入不同的兩個地方是:
(1)、在請求地址上不需要指定 ID,讓ES自動幫我們創(chuàng)建ID!
(2)、請求方式為POST方式
POST 127.0.0.1:9500/people/man
請求參數(shù):
{
"name":"dufy_auto_id",
"age":37,
"birth":"1982-09-28",
"country":"China"
}
請求結(jié)果:
{
"_index": "people",
"_type": "man",
"_id": "zmLSUGUBWifqa4luPRp5", # 自動創(chuàng)建ID
"_version": 1,
"result": "created", # 標識創(chuàng)建一個文檔
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
使用Head插件查看數(shù)據(jù):

4.3 、修改
直接修改文檔
POST 127.0.0.1:9500/people/man/1/_update
注意:需要在請求的地址后面加上 _update,標識是一個修改操作。
請求參數(shù):
{
"doc":{
"name":"dufy_update"
}
}
請求響應結(jié)果:
{
"_index": "people",
"_type": "man",
"_id": "1", # 標識文檔的ID為1
"_version": 2,
"result": "updated", # 標識修改一個文檔
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
通過Head插件查看,發(fā)現(xiàn)文檔ID為1 name已經(jīng)修改了。
腳本修改文檔
腳本修改和直接修改的API是一樣的,只是參數(shù)有些區(qū)別。
POST 127.0.0.1:9500/people/man/1/_update
第一種方式請求參數(shù):
{
"script":{
"lang":"painless" , # ES 腳本語言
"inline":"ctx._source.age += 10" #ctx:es上下文,_source:代表es當前的文檔,age:字段
}
}
第二種方式請求參數(shù):
{
"script":{
"lang":"painless" ,
"inline":"ctx._source.age = params.age",
"params":{ #使用params 指定數(shù)據(jù)值
"age":80
}
}
}
4.4、刪除
刪除文檔
DELETE 127.0.0.1:9500/people/man/1
使用delete請求,通過文檔的ID進行刪除操作。
{
"_index": "people",
"_type": "man",
"_id": "1",
"_version": 5,
"result": "deleted", # 標識刪除一個文檔
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 5,
"_primary_term": 1
}
刪除索引
刪除操作是一個比較危險的操作,因為索引一旦刪除,對應的所有數(shù)據(jù)全部被刪除了。
可以通過Head插件刪除。確認輸入
刪除,索引就刪除了。-
使用 PostMan進行刪除,使用 請求,只輸入請求的索引
127.0.0.1:9500/people
4.5、查詢-重點
查詢功能是使用過操作比較頻繁的。
首先進行數(shù)據(jù)初始化,創(chuàng)建一個book 的索引,然后插入一些數(shù)據(jù)。具體的創(chuàng)建索引和插入數(shù)據(jù),查看之前內(nèi)容。
PUT 127.0.0.1:9500/book
結(jié)構(gòu)化創(chuàng)建:
{
"mappings":{
"novel":{
"properties":{
"author":{
"type":"text"
},
"word_count":{
"type":"integer"
},
"publish_date":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"title":{
"type":"keyword"
}
}
}
}
}
插入文檔數(shù)據(jù):
POST 127.0.0.1:9500/book/novel/1
{
"title":"Nginx",
"word_count":5000,
"publish_date":"2992-09-28",
"author":"zhangyc"
}

簡單查詢
GET 127.0.0.1:9500/book/novel/4
{
"_index": "book",
"_type": "novel",
"_id": "4",
"_version": 1,
"found": true,
"_source": { # 查詢出來索引為book,類型是novel的ID=4 的文檔數(shù)據(jù)
"title": "Dubbo",
"word_count": 8000,
"publish_date": "1992-09-28",
"author": "alibb"
}
}
條件查詢
POST 127.0.0.1:9500/book/_search
- 查詢?nèi)繑?shù)據(jù)
{
"query":{ # 查詢是以query為關(guān)鍵詞的
"match_all":{} # 查詢?nèi)康臄?shù)據(jù)
}
}
返回結(jié)果:
{
"took": 8, # 接口響應花費的時間/ms
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 5, # 總共數(shù)據(jù)5條
"max_score": 1,
"hits": [ # 擊中,也就是響應的全部數(shù)據(jù),hits默認返回的數(shù)據(jù)為10條,可以修改!
{
"_index": "book",
"_type": "novel",
"_id": "5",
"_score": 1,
"_source": {
"title": "Nginx",
"word_count": 5000,
"publish_date": "2992-09-28",
"author": "zhangyc"
}
},
{....} #其他的數(shù)據(jù)信息
}
]
}
}
修改 hits默認返回數(shù)據(jù)的總數(shù)。
{
"query":{ # 查詢是以query為關(guān)鍵詞的
"match_all":{} # 查詢?nèi)康臄?shù)據(jù)
},
"size":2 # 返回數(shù)據(jù)的總數(shù)
}
-
關(guān)鍵詞查詢
POST 127.0.0.1:9500/book/_search
{
"query":{
"match":{
"title": "Redis實戰(zhàn)"
},
# 默認 排序 使用 _score
"sort":[ # 如何查詢數(shù)據(jù)較多,可以進行排序操作
{"publish_date":{"order":"desc"}}
]
}
}
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "book",
"_type": "novel",
"_id": "3",
"_score": 0.2876821,
"_source": {
"title": "Redis實戰(zhàn)",
"word_count": 2000,
"publish_date": "1582-09-28",
"author": "marry"
}
}
]
}
}
聚合查詢
POST 127.0.0.1:9500/book/_search
- 對書籍的字數(shù)進行聚合
查詢參數(shù):
{
"aggs":{
"groud_word_count":{ # 自定義聚合名稱
"terms":{
"field":"word_count"
}
}
}
}
返回結(jié)果:
{
# 其他數(shù)據(jù)省略
"aggregations": {
"groud_word_count": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 5000,
"doc_count": 2 # 文檔總數(shù)
},
{
"key": 2000,
"doc_count": 1
},
{
"key": 8000,
"doc_count": 1
},
{
"key": 10000,
"doc_count": 1
}
]
}
}
}
上面這個是單個聚合,多個聚合同理:
{
"aggs":{
"groud_word_count":{ # 自定義聚合名稱
"terms":{
"field":"word_count"
}
},
"groud_title":{ # 自定義聚合名稱
"terms":{
"field":"title"
}
}
}
}
- 進行函數(shù)計算
{
"aggs":{
"grades_word_count":{
"stats":{ #統(tǒng)計數(shù)據(jù) min 、max、avg、avg
"field":"word_count"
}
}
}
}
返回結(jié)果:
"aggregations": { # 聚合
"grades_word_count": {
"count": 5,
"min": 2000,
"max": 10000,
"avg": 6000,
"sum": 30000
}
}
五、ElasticSearch 高級查詢
子條件查詢
特定字段查詢 所指特定值
1、Query Context
在查詢過程中,除了判斷文檔是否滿足查詢條件外,ES還會計算一個_score來標識匹配的程度,旨在判斷目標文檔和查詢條件匹配的有多好(匹配度)!
- 全文本查詢 —— 針對文本類型數(shù)據(jù)
- 字段級別查詢——針對結(jié)構(gòu)化數(shù)據(jù),如數(shù)字、日期等
{
"query":{
"multi_match":{ # 多條件查詢
"query":"Redis",
"fields":["title","author"]
}
}
}
語法查詢:
{
"query":{
"query_string":{
"query":"入門 OR Redis",
"fields":["title","author"]
}
}
}
字段級別的查詢:
{
"query":{
"term":{
"word_count":5000
}
}
}
字數(shù)或者日期范圍:
{
"query":{
"range":{
"word_count":{
"gte":1000,
"lte":5000
}
}
}
}
2、Filter Context
{
"query":{
"bool":{
"filter":{
"term":{
"word_count":5000
}
}
}
}
}
復合條件查詢
以一定的邏輯組合子條件查詢,結(jié)合了Query和Filter Context
固定分數(shù)查詢
布爾查詢
六、ElasticSearch 實戰(zhàn)演練
1、配置Spring boot ElasticSearch開發(fā)環(huán)境
1、創(chuàng)建Spring boot web項目,spring boot 使用2.0.4版本, elasticsearch為5.6.10
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--引入ELasticSearch的依賴包,默認使用elasticsearch5.6.10版本-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!--需要引入transport-netty3-client,否則會啟動報錯-->
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty3-client</artifactId>
<version>5.6.10</version>
</dependency>
2、配置代碼
/**
* ES 配置類
* @author:dufyun
* @version:1.0.0
* @date 2018/8/19
* @update:[日期YYYY-MM-DD] [更改人姓名][變更描述]
*/
@Configuration
public class ElasticSearchConfig {
private static final Logger logger = LoggerFactory.getLogger(ElasticSearchConfig.class);
@Bean
public TransportClient transportClient() {
logger.info("初始化開始。。。。。");
TransportClient client = null;
try {
TransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName("localhost"),
Integer.valueOf(9300));
// 配置信息
Settings esSetting = Settings.builder()
.put("cluster.name","myEsCluster")
.build();
//配置信息Settings自定義,下面設置為EMPTY
client = new PreBuiltTransportClient(esSetting);
client.addTransportAddresses(transportAddress);
} catch (Exception e) {
logger.error("elasticsearch TransportClient create error!!!", e);
}
return client;
}
}
也可以使用配置文件!
es.hostName=localhost
es.transport=9300
es.cluster.name=myEsCluster
@Configuration
@PropertySource(value={"classpath:elasticsearch.properties"}) // 加載 指定的配置,只支持properti
public class ElasticSearchConfig {
private static final Logger logger = LoggerFactory.getLogger(ElasticSearchConfig.class);
@Value("${es.hostName}")
private String hostName;
@Value("${es.transport}")
private Integer transport;
@Value("${es.cluster.name}")
private String clusterName;
@Bean
public TransportClient transportClient() {
LOGGER.info("初始化開始。。。。。");
TransportClient client = null;
try {
TransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName(hostName),
Integer.valueOf(transport));
// 配置信息
Settings esSetting = Settings.builder()
.put("cluster.name",clusterName)
.build();
//配置信息Settings自定義,下面設置為EMPTY
client = new PreBuiltTransportClient(esSetting);
client.addTransportAddresses(transportAddress);
} catch (Exception e) {
logger.error("elasticsearch TransportClient create error!!!", e);
}
return client;
}
}
3、使用單元測試進行驗證
@Autowired
private TransportClient client;
@Test
public void contextLoads() {
System.out.println(client);
//org.elasticsearch.transport.client.PreBuiltTransportClient@6c9b44bf
}
2、接口開發(fā)
1、新增圖書信息功能開發(fā)
2、修改圖書信息功能開發(fā)
3、刪除功能開發(fā)
4、綜合查詢接口開發(fā)
代碼如下:
/**
* ES book索引 控制器
* @author:dufyun
* @version:1.0.0
* @date 2018/8/19
* @update:[日期YYYY-MM-DD] [更改人姓名][變更描述]
*/
@Controller
public class BookController {
@Autowired
private TransportClient client;
/**
* http://localhost:8080/get/book/novel?id=2
* 獲取Es中數(shù)據(jù)
* @param id
* @return
*/
@GetMapping(value = "/get/book/novel")
@ResponseBody
public ResponseEntity getBook(@RequestParam("id") String id) {
if (StringUtils.isEmpty(id)) {
return new ResponseEntity("ID不能為空!", HttpStatus.NOT_FOUND);
}
GetResponse result = client.prepareGet("book", "novel", id).get();
if (!result.isExists()) {
return new ResponseEntity("資源沒有找到!", HttpStatus.NOT_FOUND);
}
return new ResponseEntity(result.getSource(), HttpStatus.OK);
}
/**
* 添加文檔數(shù)據(jù)
* http://localhost:8080/add/book/novel
* form-data
* @param title
* @param author
* @param word_count
* @param publish_date
* @return
*/
@PostMapping(value = "/add/book/novel")
@ResponseBody
public ResponseEntity addBook(@RequestParam("title") String title, @RequestParam("author") String author,
@RequestParam("word_count") Integer word_count,
@RequestParam("publish_date") String publish_date) {
try {
/**
* 要加 startObject,否則出現(xiàn) Can not write a field name, expecting a value 錯誤!
*/
XContentBuilder builder = XContentFactory.jsonBuilder().startObject().field("title", title)
.field("author", author).field("word_count", word_count)
.field("publish_date", publish_date).endObject();
IndexResponse indexResponse = client.prepareIndex("book", "novel").setSource(builder).get();
return new ResponseEntity(indexResponse.getId(), HttpStatus.INTERNAL_SERVER_ERROR);
} catch (IOException e) {
e.printStackTrace();
new ResponseEntity("內(nèi)部服務錯誤!", HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity("插入出錯!", HttpStatus.INTERNAL_SERVER_ERROR);
}
/**
* 刪除Es中數(shù)據(jù)
* localhost:8080/del/book/novel?id=sdfhUWUB1-6vN1-K8u5f
* @param id
* @return
*/
@DeleteMapping(value = "/del/book/novel")
@ResponseBody
public ResponseEntity delBook(@RequestParam("id") String id) {
if (StringUtils.isEmpty(id)) {
return new ResponseEntity("ID不能為空!", HttpStatus.NOT_FOUND);
}
DeleteResponse result = client.prepareDelete("book", "novel", id).get();
return new ResponseEntity(result.toString(), HttpStatus.OK);
}
/**
* 更新文檔
*
* @param id
* @param title
* @param author
* @param word_count
* @param publish_date
* @return
*/
@PutMapping(value = "/update/book/novel")
@ResponseBody
public ResponseEntity updateBook(@RequestParam("id") String id,
@RequestParam(value = "title",required = false) String title,
@RequestParam(value = "author",required = false) String author,
@RequestParam(value = "word_count",required = false) Integer word_count,
@RequestParam(value = "publish_date",required = false) String publish_date) {
if (StringUtils.isEmpty(id)) {
return new ResponseEntity("ID不能為空!", HttpStatus.NOT_FOUND);
}
UpdateRequest updateRequest = new UpdateRequest("book","novel",id);
try {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
if (!StringUtils.isEmpty(title)){
builder.field("title", title);
}
if (!StringUtils.isEmpty(author)){
builder.field("author", author);
}
if (!StringUtils.isEmpty(word_count)){
builder.field("word_count", word_count);
}
if (!StringUtils.isEmpty(publish_date)){
builder.field("publish_date", publish_date);
}
builder.endObject();
updateRequest.doc(builder);
UpdateResponse updateResponse = client.update(updateRequest).get();
return new ResponseEntity(updateResponse.getId(), HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity("內(nèi)部錯誤!", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
/**
* localhost:8080/query/book/novel
* 復合查詢接口
* @param title
* @param author
* @param gt_word_conut
* @param lt_word_conut
* @return
*/
@PostMapping(value = "/query/book/novel")
@ResponseBody
public ResponseEntity queryBook(
@RequestParam(value = "title",required = false) String title,
@RequestParam(value = "author",required = false) String author,
@RequestParam(value = "gt_word_conut",defaultValue = "0") int gt_word_conut,
@RequestParam(value = "lt_word_conut",required = false) Integer lt_word_conut) {
BoolQueryBuilder boolQuy = QueryBuilders.boolQuery();
if(!StringUtils.isEmpty(title)){
boolQuy.must(QueryBuilders.matchQuery("title", title));
}
if(!StringUtils.isEmpty(author)){
boolQuy.must(QueryBuilders.matchQuery("author", author));
}
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("word_count").from(gt_word_conut);
if(lt_word_conut != null && gt_word_conut >0){
rangeQueryBuilder.to(lt_word_conut);
}
boolQuy.filter(rangeQueryBuilder);
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("book")
.setTypes("novel")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQuy)
.setFrom(0)
.setSize(10);
SearchResponse searchResponse = searchRequestBuilder.get();
List<Map<String, Object>> lists = new ArrayList<>();
for (SearchHit hit:searchResponse.getHits().getHits()) {
lists.add(hit.getSource());
}
return new ResponseEntity(lists,HttpStatus.OK);
}
}
七、ElasticSearch 總結(jié)
- ES簡介——使用場景(重要性),提高競爭力
- 安裝ES-單機-分布式
- 核心基礎概念
- 基本使用方法 ——增刪查改
- 高級查詢語法——重點和難點
- 實戰(zhàn)演練

實戰(zhàn)演練源碼
springboot-elasticsearch
如果您覺得這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到,謝謝!
如果帥氣(美麗)、睿智(聰穎),和我一樣簡單善良的你看到本篇博文中存在問題,請指出,我虛心接受你讓我成長的批評,謝謝閱讀!
祝你今天開心愉快!
歡迎訪問我的csdn博客,我們一同成長!
不管做什么,只要堅持下去就會看到不一樣!在路上,不卑不亢!
博客首頁 : http://blog.csdn.net/u010648555
? 每天都在變得更好的阿飛