javascript
Elasticsearch-06 Spring Boot 2.0.9整合ElasticSearch5.6.16
文章目錄
- 概述
- 官方JAVA API文檔
- 工程
- pom.xml
- es配置文件
- Es配置類
- 控制層
- 簡單查詢
- 新增數據
- 刪除數據
- 更新數據
- 復合查詢
- 其他
- 新建索引
- 刪除索引
- 判斷index中某個type是否存在
- spring-data-elasticsearch 操作ES
- 代碼
概述
前面幾篇,學習了ES的基本操作,那我們這里集成到代碼中吧。 我們這里沒有使用Spring 提供的 spring-boot-starter-data-elasticsearch,使用的是ES原生的API 。
官方JAVA API文檔
當前7.0
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html
5.6
https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.6/index.html
工程
ES服務端的版本 5.6.16 ,工程里es客戶端的版本最好和服務端保持一致 。 正好Spring Boot 2.0.9RELEASE版本搭配transport里es是5.6.16版本。
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.9.RELEASE</version><relativePath /> <!-- lookup parent from repository --></parent><groupId>masterSpringMvc</groupId><artifactId>springBootElasticSearch</artifactId><version>0.0.1-SNAPSHOT</version><name>springBootElasticSearch</name><description>masterSpringMvc project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>transport</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>es配置文件
# Elasticsearch elasticsearch.ip=127.0.0.1 #9200端口是RESTFul API來訪問ElasticSearch的端口,9300端口是es節點通訊的默認端口,給java程序用的配置9300elasticsearch.port=9300 elasticsearch.pool=5# 集群的名字,和elasticsearch.yml中的cluster.name保持一致elasticsearch.cluster.name=artisanEs配置類
package com.artisan.config;import java.net.InetAddress; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration public class ESConfig {private static final Logger logger = LoggerFactory.getLogger(ESConfig.class);@Value("${elasticsearch.ip}")private String hostName;@Value("${elasticsearch.port}")private String port;@Value("${elasticsearch.cluster.name}")private String clusterName;@Value("${elasticsearch.pool}")private String poolSize;@Beanpublic TransportClient transportClient() {logger.info("Elasticsearch begin to init ");TransportClient transportClient = null;try {// 地址信息InetSocketTransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName(hostName), Integer.valueOf(port));// 配置信息Settings esSetting = Settings.builder().put("cluster.name", clusterName) // 集群名字.put("client.transport.sniff", true)// 增加嗅探機制,找到ES集群.put("thread_pool.search.size", Integer.parseInt(poolSize))// 線程池個數.build();// 配置信息Settings自定義transportClient = new PreBuiltTransportClient(esSetting);transportClient.addTransportAddresses(transportAddress);} catch (Exception e) {logger.error("TransportClient create error", e);}return transportClient;} }控制層
簡單起見,我們直接在Controller層操作ES吧,僅僅是為了測試下功能。
簡單查詢
先寫個簡單的根據id獲取數據的方法來測試下班
package com.artisan.controller;import java.util.Map;import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.client.transport.TransportClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController;@RestController public class ESController {@Autowiredprivate TransportClient client;@GetMapping("/book/novel/{id}")public ResponseEntity<Map<String, Object>> getByIdFromES(@PathVariable String id){GetResponse response = this.client.prepareGet("book", "novel", id).get();if (!response.isExists()) {return new ResponseEntity<>(HttpStatus.NOT_FOUND);}return new ResponseEntity<Map<String, Object>>(response.getSource(),HttpStatus.OK);}}啟動下服務,在瀏覽器或者postman中訪問下吧
我們通過head插件來看下id=11的數據
OK,可以訪問到正確的數據。
新增數據
ESController新增add方法
@PostMapping("/book/novel/add")public ResponseEntity<String> add(NovelDTO novel) {try {XContentBuilder builder = XContentFactory.jsonBuilder().startObject().field("title", novel.getTitle()).field("author", novel.getAuthor()).field("word_count", novel.getWordCount()).field("public_date", novel.getPublishDate().getTime()).endObject();IndexResponse response = this.client.prepareIndex("book", "novel").setSource(builder).get();return new ResponseEntity<String>(response.getId(), HttpStatus.OK);} catch (IOException e) {e.printStackTrace();return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);}}我們把數據請求參數封裝到了NovelDTO 中
package com.artisan.dto;import java.util.Date;import org.springframework.format.annotation.DateTimeFormat;public class NovelDTO {private String title;private String author;private String wordCount;@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")private Date publishDate;// set/get方法 省略 }啟動服務,POST http://localhost:8080/book/novel/add
head插件中查看數據 訪問 http://localhost:9100/
新增成功
如果要想用JSON傳的話,需要在方法入參前加入 @RequestBody ,postman中更改如下
public ResponseEntity<String> add(@RequestBody NovelDTO novel) {}刪除數據
@DeleteMapping("/book/novel/del")public ResponseEntity<String> delete(String id ){DeleteResponse response = this.client.prepareDelete("book", "novel", id).get();return new ResponseEntity<String>(response.getResult().toString(),HttpStatus.OK);}把剛才新增的數據刪掉
通過head插件查看已經沒有該記錄了,刪除OK
更新數據
舉個例子,根據id更新title
/*** 根據id 修改title* @param id* @param title* @return*/@PutMapping("/book/novel/update")public ResponseEntity<String> update(@RequestParam(name="id")String id ,@RequestParam(name="title") String title){UpdateRequest updateRequest = new UpdateRequest("book", "novel", id);try {XContentBuilder builder = XContentFactory.jsonBuilder().startObject().field("title",title).endObject();updateRequest.doc(builder);UpdateResponse response = this.client.update(updateRequest).get();return new ResponseEntity<String>(response.getResult().toString(), HttpStatus.OK);} catch (Exception e) {e.printStackTrace();return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);} }head插件查看
復合查詢
/*** 綜合查詢* @param title* @param author* @param gtWordCount* @param ltWordCount* @return*/@PostMapping("/book/novel/query")public ResponseEntity<List<Map<String, Object>>> query(@RequestParam(name="title",required=false)String title , @RequestParam(name="author",required=false)String author ,@RequestParam(name="gtWordCount",defaultValue="0") Integer gtWordCount ,@RequestParam(name="ltWordCount",required=false) Integer ltWordCount ) {BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();if (title !=null) {boolQueryBuilder.must(QueryBuilders.matchQuery("title", title));}if (author !=null) {boolQueryBuilder.must(QueryBuilders.matchQuery("author", author));}RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("word_count").from(gtWordCount);if (ltWordCount != null && ltWordCount > 0) {rangeQueryBuilder.to(ltWordCount);}// 關聯boolQueryBuilder.filter(rangeQueryBuilder);SearchRequestBuilder builder = this.client.prepareSearch("book").setTypes("novel").setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(boolQueryBuilder).setFrom(0).setSize(10);System.out.println("請求JSON數據:\n" + builder);SearchResponse response = builder.get();List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();for(SearchHit searchHit : response.getHits()) {list.add(searchHit.getSource());}return new ResponseEntity<List<Map<String, Object>>>(list, HttpStatus.OK);}看下控制臺輸出的
請求JSON數據:
{"from" : 0,"size" : 10,"query" : {"bool" : {"must" : [{"match" : {"title" : {"query" : "Elasticsearch","operator" : "OR","prefix_length" : 0,"max_expansions" : 50,"fuzzy_transpositions" : true,"lenient" : false,"zero_terms_query" : "NONE","boost" : 1.0}}}],"filter" : [{"range" : {"word_count" : {"from" : 500,"to" : null,"include_lower" : true,"include_upper" : true,"boost" : 1.0}}}],"disable_coord" : false,"adjust_pure_negative" : true,"boost" : 1.0}} }使用postman測試下 ,返回了3條數據,符合預期。
其他
上面通過代碼實現了數據的CRUD操作,那么我們把多索引和type的操作也嘗試寫下吧
工具類
package com.artisan.utils;import javax.annotation.PostConstruct;import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.client.transport.TransportClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;@Component public class ESUtil {private static final Logger logger = LoggerFactory.getLogger(ESUtil.class);@Autowiredprivate TransportClient transportClient;private static TransportClient client;@PostConstructpublic void init() {client = this.transportClient;}/*** 創建索引** @param index* @return*/public static boolean createIndex(String index) {if (!isIndexExist(index)) {logger.info("Index is not exits!");CreateIndexResponse indexresponse = client.admin().indices().prepareCreate(index).execute().actionGet();logger.info("執行建立成功?" + indexresponse.isAcknowledged());return indexresponse.isAcknowledged();}return false;}/*** 刪除索引** @param index* @return*/public static boolean deleteIndex(String index) {if (!isIndexExist(index)) {logger.info("Index is not exits!");}DeleteIndexResponse dResponse = client.admin().indices().prepareDelete(index).execute().actionGet();if (dResponse.isAcknowledged()) {logger.info("delete index " + index + " successfully!");} else {logger.info("Fail to delete index " + index);}return dResponse.isAcknowledged();}/*** 判斷索引是否存在** @param index* @return*/public static boolean isIndexExist(String index) {IndicesExistsResponse inExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet();if (inExistsResponse.isExists()) {logger.info("Index [" + index + "] is exist!");} else {logger.info("Index [" + index + "] is not exist!");}return inExistsResponse.isExists();}/*** 判斷index下指定type是否存在* * @param index* @param type* @return*/public static boolean isTypeExist(String index, String type) {return isIndexExist(index)? client.admin().indices().prepareTypesExists(index).setTypes(type).execute().actionGet().isExists(): false;}}新建索引
@SuppressWarnings({ "rawtypes", "unchecked" })@PostMapping("/index/create")public ResponseEntity create(String index){if (ESUtil.createIndex(index)) {return new ResponseEntity(Boolean.TRUE,HttpStatus.OK);}else {return new ResponseEntity(HttpStatus.FOUND);}}測試
head查看下
刪除索引
@SuppressWarnings({ "rawtypes", "unchecked" })@PostMapping("/index/delete")public ResponseEntity deleteIndex(String index){if (ESUtil.deleteIndex(index)) {return new ResponseEntity(Boolean.TRUE,HttpStatus.OK);}else {return new ResponseEntity(HttpStatus.NOT_FOUND);}}測試下
head查看,已經刪除成功
判斷index中某個type是否存在
@SuppressWarnings({ "rawtypes", "unchecked" })@PostMapping("/index/isTypeExist")public ResponseEntity isTypeExist(String index,String type){if (ESUtil.isTypeExist(index,type)) {return new ResponseEntity(Boolean.TRUE,HttpStatus.OK);}else {return new ResponseEntity(HttpStatus.NOT_FOUND);}}測試一下
spring-data-elasticsearch 操作ES
https://docs.spring.io/spring-data/
我們也可以用Spring給我們提供的封裝好的 ElasticsearchTemplate 更方便的操作ES,這里我就不演示了,和data jpa操作很像,比較簡單。
https://spring.io/projects/spring-data-elasticsearch
https://github.com/spring-projects/spring-data-elasticsearch
如果也是使用spring boot集成的話,就用 spring-boot-starter-data-elasticsearch 這個maven的依賴,帶有starter的這種。
代碼
Github: https://github.com/yangshangwei/springBootElasticSearch
總結
以上是生活随笔為你收集整理的Elasticsearch-06 Spring Boot 2.0.9整合ElasticSearch5.6.16的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch-05Elas
- 下一篇: 白话Elasticsearch01- 结