前言:在上一篇博客中,我介紹了從零開始安裝ElasticSearch,es是能夠理解爲一個操做數據的中間件,能夠把它做爲數據的存儲倉庫來對待,它具有強大的吞吐能力和計算能力,其基於Lucene服務器開發,在搜索領域具備統治般的地位。平時能夠經過命令來執行語句來查詢ES,可是在實際的開發中,仍是以使用API居多,關於ES的第三方框架有不少,好比BBOSS、spring也對其進行封裝叫作spring-elasticsearch-data,本篇博客,咱們就來聚焦Spring的官方API,來作一個基本的demo實現api來操做Es(elasticsearch的簡稱)html
本篇博客的目錄java
一:ElasticSearch的基本概念node
二:ElasticSearch5.2.2的安裝mysql
三:ElasticSearch的官方API與Demo實現spring
四:總結sql
一:ElasticSearch的基本概念docker
1.1:索引 index數據庫
索引是ES存儲數據的基本頂層單元目錄.它比如就是關係型數據庫中的數據庫,是存儲數據的地方。當搜索數據的時候,會直接從索引中查取,注意這裏要與關係型數據的中的索引區分,他們是徹底不一樣的概念。index的名字必須是小寫,不能包含逗號、下劃線或者大寫字母json
1.2:類型 typebootstrap
type表示一類或者一種事物的抽象,在關係型數據庫中咱們常常將一類結構類似的數據放在一個表裏,而在elasticsearch中,使用相同類型的type表示相同的一類事物,它至關於關係型數據庫中的表(table),用於描述文檔中的各個字段的定義。每一個type都有本身的映射(mapping)或者結構定義。type的名字能夠是大寫或者小寫,不能包含下劃線或者逗號。
1.3:文檔 document
document是index中的單條數據序列化成的json格式的數據,它以惟一id(_id)存儲在ES中,至關於關係表的數據行,存儲數據的載體,包含一個或多個存有數據的字段;
·字段(Field):文檔的一個Key/Value對;
·詞(Term):表示文本中的一個單詞;
·標記(Token):表示在字段中出現的詞,由該詞的文本、偏移量(開始和結束)以及類型組成
1.4:Node 與 Cluster
Elastic 本質上是一個分佈式數據庫,容許多臺服務器協同工做,每臺服務器能夠運行多個 Elastic 實例。單個 Elastic 實例稱爲一個節點(node)。一組節點構成一個集羣(cluster)。
1.5:與mysql進行比較
二:ElasticSearch5.2.2的安裝
上一篇博客已經介紹了ES2.0版本的安裝,這篇就再也不贅述了。不過我仍是決定說一些在安裝過程當中的坑,安裝ES的坑確實不少,樓主分別安裝了2.0版本,5.5.2版本,5.2.2版本,還用docker安裝了,可是由於docker玩的不夠熟練,在配置文件上更改仍是出了不少問題,最終仍是靠傳統的安裝方式解決的。接下來就說說ES安裝過程當中的一些坑以及主要的點:
2.1:cannot allocate memory
這個是由於ES沒法獲取到足夠的內存,解決辦法就是,修改elasticseach的config目錄下的jvm.options,ES默認的大小是1G,最好修改爲2的整數倍的容量,具體依本身的內存而定,我修改的是256m
2.2:Exception in thread "main" java.lang.RuntimeException: don't run elasticsearch as root.
沒法以root用戶啓動,ES直接以root用戶是沒法啓動的,解決辦法很簡單,就是創建一個ES的專用的組和用戶:
groupadd elasticsearchgroup
useradd elasticsearchgroup -g elasticsearch -p elasticsearch
chown -R elasticsearchgroup:elasticsearch elasticsearch-5.2.2
這裏是先創建了一個elasticsearch的組,而後再添加elasticsearch這個用戶,密碼也是elasticsearch,再給ES的安裝目錄添加權限
2.3:ERROR: bootstrap checks failed max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
解決辦法就是修改系統的修改配置sysctl.conf最大文件交換數量:
vi.sysctl.conf
vm.max_map_count=655360
sysctl -p
2.4: org.elasticsearch.client.transport.NoNodeAvailableException
這個錯誤,是後臺在鏈接APi出現的錯誤,爲了解決這個問題,我花了好久(下面會說到版本號的問題),還有須要更改一下配置:
首先是編輯config目錄下的 elasticsearch.yml文件:
這裏的host要把#號打開,而後寫上本身的外網IP的地址,還有cluster.name的名字也要記住,它在配置ES中須要用到
三:ElasticSearch的官方API與Demo實現
3.1.1:引入TransPort5.2.2
這裏必須注意引入5.2.2版本,由於我服務上安裝的ES就是5.2.2版本。ES官方API衆多,每一個版本之間不是互相兼容的,若是引入的版本對應,會報一個錯誤:
org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available.(這個錯誤折磨了我好久,因此必定要以本身的服務器上的版本爲準,引入netty和elasticsearch、transport的版本互相對應)
<dependency> <groupId>org.elasticsearch.plugin</groupId> <artifactId>transport-netty4-client</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.2.2</version> </dependency>
3.1.2:springboot配置ES
新建一個類叫作ESconfig,主要是配置ES服務器的IP和端口(注意這裏是9300而不是9200),9300是ES的TCP服務端口,而後實例化客戶端;
package com.wyq.elasticsearch.easticsearchtest.config; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.net.InetAddress; import java.net.UnknownHostException; @Configuration public class ESConfig { @Bean public TransportClient client() throws UnknownHostException { // 9300是es的tcp服務端口 final String host = "176.122.132.220"; InetSocketTransportAddress node = new InetSocketTransportAddress( InetAddress.getByName(host), 9300); // 設置es節點的配置信息 Settings settings = Settings.builder() .put("cluster.name", "application").build(); // 實例化es的客戶端對象 TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(node); return client; } }
3.1.3:添加index
若是在ES裏面添加一個index,咱們須要如下命令,解釋如下就是指定數據的index和type,在裏面在指定fieldname
curl -X PUT 'ip:port/index/type/id’ -d '
{
「filedname」: 「xxx」
}'
ES提供了同等的API來供咱們使用,按照下面的例子,咱們將會添加一個index叫作animal,type叫作person的數據,並經過Springboot注入TransPortClient,而後用MVC來獲取請求參數,交給ES的api去處理:XContentFactory.jsonBuilder()去拼接不一樣的json字符串,用client去處理:
@RestController public class ElasticSearchDemoController { @Autowired private TransportClient client; public static final String index = "product"; public static final String type = "person"; /** * 添加一我的的數據 * * @param name 名字 * @param sex 性別 * @param message 說明 * @param job 工做 * @param onlyMark 惟一標誌 * @return */ @PostMapping("/es/add") public ResponseEntity add(@RequestParam("name") String name, @RequestParam("sex") int sex, @RequestParam("message") String message, @RequestParam("job") String job, @RequestParam("onlyMark") int onlyMark) { try { // 將參數build成一個json對象 XContentBuilder content = XContentFactory.jsonBuilder() .startObject() .field("uniqueId", onlyMark) .field("name", name) .field("sex", sex) .field("message", message) .field("job", job) .endObject(); IndexResponse response = client.prepareIndex(index, type) .setSource(content) .get(); return ResponseEntity.getSuccess(response.getResult()+""+response.getId(), HttpStatus.OK.value()); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value()); } } }
3.1.4:查詢index
經過id去查詢,而後經過client(TransPortClient)的prepareGet方法去查詢,最後返回一個GetResponse結果真後獲取它的source結果:
/** * 按id查詢 * * @param id * @return */ @GetMapping("/es/get") public ResponseEntity searchById(@RequestParam("id") String id) { if (id.isEmpty()) { return new ResponseEntity(HttpStatus.NOT_FOUND.value()); } // 經過索引、類型、id向es進行查詢數據 GetResponse response = client.prepareGet(index, type, id).get(); if (!response.isExists()) { return new ResponseEntity(HttpStatus.NOT_FOUND.value()); } return ResponseEntity.getSuccess(response.getSource(), HttpStatus.OK.value()); }
3.1.5:刪除index
一樣刪除index,也是經過id來匹配的,id是惟一標誌,而後交給TransPort的prepareDelete方法去刪除
/** * 按id刪除數據 * * @param id * @return */ @GetMapping("/es/delete") public ResponseEntity delete(@RequestParam("id") String id) { DeleteResponse response = client.prepareDelete(index, type, id).get(); return ResponseEntity.getSuccess(response.getResult(), HttpStatus.OK.value()); }
3.1.6:更新index
經過獲取更新的內容,而後交給TransPort的update方法去更新須要更新的字段,最終返回更新的內容:
/** * 根據文檔id更新某個文檔的數據 * * @param uniqueId * @param name * @param sex * @param message * @param job * @return */ @PutMapping("/es/update") public ResponseEntity update(@RequestParam("id") String id, @RequestParam(value = "name", required = false) String name, @RequestParam(value = "sex", required = false) Integer sex, @RequestParam(value = "message", required = false) String message, @RequestParam(value = "job", required = false) String job, @RequestParam(value = "uniqueId", required = false) Integer uniqueId){ UpdateRequest update = new UpdateRequest(index, type, id); try { XContentBuilder builder = XContentFactory.jsonBuilder() .startObject(); if (Objects.nonNull(name)) { builder.field("name", name); } if (Objects.nonNull(sex)) { builder.field("sex", sex); } if (Objects.nonNull(message)) { builder.field("message", message); } if (Objects.nonNull(job)) { builder.field("job", job); } if (Objects.nonNull(uniqueId)){ builder.field("uniqueId",uniqueId); } builder.endObject(); update.doc(builder); UpdateResponse response = client.update(update).get(); return ResponseEntity.getSuccess(response.getResult(), HttpStatus.OK.value()); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value()); } }
3.2:測試
3.2.1:打開postman,而後咱們來先來添加一個index,添加一些屬性,後臺提示成功:咱們在去ES中查詢一下:
3.2.2:在服務器中打開,而後輸入查詢全部index的命令,查詢animal這個index對應的數據,能夠看到咱們的數據已經順利添加:
3.2.3:查詢index
上面的方式是經過命令的方式來查詢的,咱們再來經過程序來測試查詢index,能夠看到數據查詢到了:
3.2.4:更新index
後臺經過傳入的字段對指定有值的數據進行更新,在這裏咱們更新message:
3.2.5:爲了驗證咱們的更改是否生效,咱們再查詢一下這個index,發現message已經變化了:
3.2.6:刪除index
3.2.7:一樣咱們在驗證一下是否刪除成功,能夠看出total爲0,也表明沒有數據了:
四:總結
礙於篇幅,本片博文就介紹到這裏,主要是講述了ElasticSearch的官方API的使用,以及搭建ES中的一些坑,爲了解決這些坑,我在下班之餘耗費了好幾個星期研究這些問題,ES的版本衆多,必定要注意版本的選擇。本篇博文適合入門級別,沒有介紹ES的高級特性,關於它自己具備不少高端特性,實乃搜索利器,咱們不能把它做爲數據庫來看待,實際上它自己能夠理解爲一個搜索引擎,有着豐富的使用場景,"它遠大於數據庫,存儲只是它的一個細小的功能",好了,但願本篇博客能夠幫助到你。
本篇博客的代碼分享:連接:https://pan.baidu.com/s/1k-E15_EtHArG3iYi_3wc9A 密碼:0nbp
若是關於本篇博客有任何問題,請加羣:618626589
參考文檔:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html