(2020/4/19對本文進行補充)關於springboot整個es有四種方法,分別是TransportClient、RestClient、SpringData-Es、Elasticsearch-SQL。html
官方推薦的是RestClient,我在工做中見到的是SpringData-ES,這裏舉的例子是TransportClient。java
也就是說 ↓ ↓ ↓node
若是是TransportClient,能夠參考這篇文章。mysql
若是使用的是RestClient,能夠參考這篇文章:https://www.jianshu.com/p/2ff05a83816e;這種方式也是官網推薦的;web
若是使用的是SpringData-Es,能夠參考:https://blog.csdn.net/tianyaleixiaowu/article/details/76149547/ (介紹了ElasticsearchRepoistory和ElasticsearchTemplate兩種方法的具體使用。);spring
若是使用的是Elasticsearch-SQL,面向百度,我確實太懶了,sql
一、新建一個maven項目數據庫
二、導入相應的jar包apache
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.aaa.liu.es</groupId> 8 <artifactId>SpringBootEs</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 11 <parent> 12 <groupId>org.springframework.boot</groupId> 13 <artifactId>spring-boot-starter-parent</artifactId> 14 <version>1.5.10.RELEASE</version> 15 </parent> 16 17 <!-- 18 !!!!!!!導入springboot自帶的es jar包: es-starter 19 (不能使用springboot自帶的)!!!!!!! 20 21 es的jar包 22 trasportClient jar包(就是使用Java代碼對ES進行增刪改查) 23 使用es的時候es會自動依賴log4j,若是沒有log4j的jar包,會報錯可是不影響項目正常運行(有強迫症的同窗能夠導入log4j) 24 es還會自動依賴common-lang3(基於Java.lang包中作的一層封裝,比Java.lang包功能更強大) 25 springboot 26 web-starter 27 mybatis 28 mysql 29 druid 30 configuration-properties == true(@ConfigurationProperties:從properties中讀取配置信息) 31 32 --> 33 34 <dependencies> 35 <!-- 36 springboot-starter-web 37 --> 38 <dependency> 39 <groupId>org.springframework.boot</groupId> 40 <artifactId>spring-boot-starter-web</artifactId> 41 </dependency> 42 <!-- 43 springboot-mybatis整合包 44 --> 45 <dependency> 46 <groupId>org.mybatis.spring.boot</groupId> 47 <artifactId>mybatis-spring-boot-starter</artifactId> 48 <version>1.3.0</version> 49 </dependency> 50 <!-- 51 mysql的驅動包 52 --> 53 <dependency> 54 <groupId>mysql</groupId> 55 <artifactId>mysql-connector-java</artifactId> 56 <version>5.1.38</version> 57 </dependency> 58 <!-- 59 druid鏈接池 60 --> 61 <dependency> 62 <groupId>com.alibaba</groupId> 63 <artifactId>druid</artifactId> 64 <version>1.1.10</version> 65 </dependency> 66 <!-- 67 html的thymeleaf模板 68 --> 69 <dependency> 70 <groupId>org.springframework.boot</groupId> 71 <artifactId>spring-boot-starter-thymeleaf</artifactId> 72 </dependency> 73 74 <!-- 75 fastjson包 76 --> 77 <dependency> 78 <groupId>com.fasterxml.jackson.core</groupId> 79 <artifactId>jackson-databind</artifactId> 80 <version>2.8.1</version> 81 </dependency> 82 83 <dependency> 84 <groupId>org.elasticsearch</groupId> 85 <artifactId>elasticsearch</artifactId> 86 <version>6.4.0</version> 87 </dependency> 88 89 <dependency> 90 <groupId>org.elasticsearch.client</groupId> 91 <artifactId>transport</artifactId> 92 <version>6.4.0</version> 93 <exclusions> 94 <exclusion> 95 <groupId>org.elasticsearch</groupId> 96 <artifactId>elasticsearch</artifactId> 97 </exclusion> 98 </exclusions> 99 </dependency> 100 101 <dependency> 102 <groupId>org.apache.commons</groupId> 103 <artifactId>commons-lang3</artifactId> 104 <version>3.4</version> 105 </dependency> 106 107 <dependency> 108 <groupId>commons-httpclient</groupId> 109 <artifactId>commons-httpclient</artifactId> 110 <version>3.1</version> 111 </dependency> 112 113 <!--<dependency> 114 <groupId>org.springframework.boot</groupId> 115 <artifactId>spring-boot-starter-data-elasticsearch</artifactId> 116 </dependency>--> 117 118 <dependency> 119 <groupId>org.springframework.boot</groupId> 120 <artifactId>spring-boot-configuration-processor</artifactId> 121 <optional>true</optional> 122 </dependency> 123 124 <dependency> 125 <groupId>org.apache.logging.log4j</groupId> 126 <artifactId>log4j-core</artifactId> 127 <version>2.9.1</version> 128 </dependency> 129 <dependency> 130 <groupId>org.apache.logging.log4j</groupId> 131 <artifactId>log4j-api</artifactId> 132 <version>2.9.1</version> 133 </dependency> 134 </dependencies> 135 136 </project>
注意:這裏不能加入springboot自帶的es-starter 的jar包,不然會報錯:org.elasticsearch.action.count.CountRequestBuilderjson
三、開始springboot項目的架構:
包:controller、Mapper、service、model、utils、config、status(枚舉)
入口類:ApplicationRun
resources:包:config、Mapper
[1] 開始咱們基本的配置:resources/config/application.properties:
1 server.port=8081 2 server.context-path=/ 3 4 spring.datasource.driver-class-name=com.mysql.jdbc.Driver 5 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis 6 spring.datasource.username=root 7 spring.datasource.password=123456 8 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 9 10 mybatis.type-aliases-package=com.aaa.liu.es.model 11 mybatis.mapper-locations=classpath:mapper/*Mapper.xml 12 13 elasticsearch.ip=192.168.134.147 14 # 若是使用的TransportClient方式進行鏈接ES,必需要使用9300端口號,使用9200端口號沒法鏈接 15 elasticsearch.port=9300 16 # ES的鏈接數(能夠同時有多少鏈接) 17 elasticsearch.pool=5 18 # 注意cluster.name須要與config/elasticsearch.yml中的cluster.name對應一致 19 elasticsearch.clusterName=my-application 20 elasticsearch.nodeName=node-1
[2] 將咱們的配置信息調用:java中的config: ESProperties類和EsConfig
1 package com.aaa.liu.es.config; 2 3 import org.springframework.boot.context.properties.ConfigurationProperties; 4 import org.springframework.stereotype.Component; 5 6 /** 7 * @Author 劉其佳 8 * @DateTime 2019/9/18 19:31 9 * @Project_Name SpringBootEs 10 */ 11 12 @Component 13 @ConfigurationProperties(prefix = "elasticsearch") 14 public class ESProperties { 15 16 private String ip; 17 private String port; 18 private String pool; 19 private String clusterName; 20 private String nodeName; 21 22 public String getIp() { 23 return ip; 24 } 25 26 public void setIp(String ip) { 27 this.ip = ip; 28 } 29 30 public String getPort() { 31 return port; 32 } 33 34 public void setPort(String port) { 35 this.port = port; 36 } 37 38 public String getPool() { 39 return pool; 40 } 41 42 public void setPool(String pool) { 43 this.pool = pool; 44 } 45 46 public String getClusterName() { 47 return clusterName; 48 } 49 50 public void setClusterName(String clusterName) { 51 this.clusterName = clusterName; 52 } 53 54 public String getNodeName() { 55 return nodeName; 56 } 57 58 public void setNodeName(String nodeName) { 59 this.nodeName = nodeName; 60 } 61 }
1 package com.aaa.liu.es.config; 2 3 import org.elasticsearch.client.transport.TransportClient; 4 import org.elasticsearch.common.settings.Settings; 5 import org.elasticsearch.common.transport.TransportAddress; 6 import org.elasticsearch.transport.client.PreBuiltTransportClient; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.boot.autoconfigure.SpringBootApplication; 9 import org.springframework.context.annotation.Bean; 10 11 import java.net.InetAddress; 12 import java.net.UnknownHostException; 13 14 /** 15 * @Author 劉其佳 16 * @DateTime 2019/9/18 19:33 17 * @Project_Name SpringBootEs 18 */ 19 @SpringBootApplication 20 public class EsConfig { 21 22 @Autowired 23 private ESProperties esProperties; 24 25 26 /** 27 * @author 劉其佳 28 * @description 29 * 建立並初始化TransportClient對象,使用該對象對ES進行增刪查改 30 * cluster.name:集羣名字 31 * node.name:節點名字 32 * client.transport.sniff:客戶端(Java項目)一致監視ES的節點狀態(節點數),再也不須要手動添加節點,若是有新的節點產生了,會自動加載進項目中 33 * thread_pool.search.size:線程池 34 * 35 * @param * param *: 36 * @date 2019/9/18 37 * @return org.elasticsearch.client.transport.TransportClient 38 * @throws 39 */ 40 @Bean("transportClient") 41 public TransportClient getTransportClient(){ 42 //一、建立TransportClient對象 43 TransportClient transportClient=null; 44 try{ 45 //二、設置Java對ES的集羣信息 46 Settings settings=Settings.builder().put("cluster.name",esProperties.getClusterName()) 47 .put("node.name", esProperties.getNodeName()) 48 .put("client.transport.sniff", true) 49 .put("thread_pool.search.size", esProperties.getPool()).build(); 50 //三、初始化TransportClient對象 51 transportClient=new PreBuiltTransportClient(settings); 52 //四、配置對ES的鏈接信息 53 TransportAddress transportAddress=new TransportAddress(InetAddress.getByName(esProperties.getIp()),Integer.parseInt(esProperties.getPort())); 54 //五、把對ES的鏈接對象放到transportClient對象中 55 transportClient.addTransportAddress(transportAddress); 56 }catch (UnknownHostException e){ 57 e.printStackTrace(); 58 } 59 return transportClient; 60 } 61 }
四、主要的核心其實在utils包中的工具類:ESUtil
1 package com.aaa.liu.es.utils; 2 3 import com.aaa.liu.es.status.StatusEnum; 4 import org.apache.commons.lang3.StringUtils; 5 import org.elasticsearch.action.ActionFuture; 6 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; 7 import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; 8 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; 9 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; 10 import org.elasticsearch.action.delete.DeleteResponse; 11 import org.elasticsearch.action.get.GetRequestBuilder; 12 import org.elasticsearch.action.get.GetResponse; 13 import org.elasticsearch.action.index.IndexResponse; 14 import org.elasticsearch.action.search.SearchRequestBuilder; 15 import org.elasticsearch.action.search.SearchResponse; 16 import org.elasticsearch.action.update.UpdateRequest; 17 import org.elasticsearch.action.update.UpdateResponse; 18 import org.elasticsearch.client.transport.TransportClient; 19 import org.elasticsearch.common.text.Text; 20 import org.elasticsearch.index.query.QueryBuilder; 21 import org.elasticsearch.search.SearchHit; 22 import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; 23 import org.elasticsearch.search.sort.SortOrder; 24 import org.springframework.beans.factory.annotation.Autowired; 25 import org.springframework.stereotype.Component; 26 27 import javax.annotation.PostConstruct; 28 import java.lang.reflect.Field; 29 import java.util.*; 30 31 /** 32 * @Author 劉其佳 33 * @DateTime 2019/9/18 20:35 34 * @Project_Name SpringBootEs 35 */ 36 @Component 37 public class ESUtil { 38 39 @Autowired 40 private TransportClient transportClient; 41 42 /** 43 * 由於該工具類中全部的方法都是靜態方法,靜態方法只能調用靜態變量 44 * 因此使用@Autowired註解所注入進的對象靜態方法不能直接調用,由於static修飾的方式不能使用普通變量 45 * 下面的@PostConstruct註解就是來解決了以上的問題 46 */ 47 private static TransportClient client; 48 49 private static Map<String, Object> resultMap = new HashMap<String, Object>(); 50 51 /** 52 * @PostContruct是spring框架的註解 spring容器初始化的時候執行該方法 53 */ 54 @PostConstruct 55 public void init() { 56 client = this.transportClient; 57 } 58 59 /** 60 * 建立索引 61 * 62 * @param index 63 * @return 64 */ 65 public static Map<String, Object> createIndex(String index) { 66 // isIndexExist:判斷索引是否存在 67 if (!isIndexExist(index)) { 68 resultMap.put("code", StatusEnum.EXIST.getCode()); 69 resultMap.put("msg", StatusEnum.EXIST.getMsg()); 70 } 71 CreateIndexResponse indexresponse = client.admin().indices().prepareCreate(index).execute().actionGet(); 72 // indexresponse.isAcknowledged():建立索引是否成功,return Boolean類型(true:表示成功,false:失敗) 73 if(indexresponse.isAcknowledged()) { 74 resultMap.put("code", StatusEnum.OPRATION_SUCCESS.getCode()); 75 resultMap.put("msg", StatusEnum.OPRATION_SUCCESS.getMsg()); 76 } else { 77 resultMap.put("code", StatusEnum.OPRATION_FAILED.getCode()); 78 resultMap.put("msg", StatusEnum.OPRATION_FAILED.getMsg()); 79 } 80 return resultMap; 81 } 82 83 /** 84 * 刪除索引 85 * 86 * @param index 87 * @return 88 */ 89 public static Map<String, Object> deleteIndex(String index) { 90 if (!isIndexExist(index)) { 91 resultMap.put("code", StatusEnum.EXIST.getCode()); 92 resultMap.put("msg", StatusEnum.EXIST.getMsg()); 93 } 94 DeleteIndexResponse dResponse = client.admin().indices().prepareDelete(index).execute().actionGet(); 95 if (dResponse.isAcknowledged()) { 96 resultMap.put("code", StatusEnum.OPRATION_SUCCESS.getCode()); 97 resultMap.put("msg", StatusEnum.OPRATION_SUCCESS.getMsg()); 98 } else { 99 resultMap.put("code", StatusEnum.OPRATION_FAILED.getCode()); 100 resultMap.put("msg", StatusEnum.OPRATION_FAILED.getMsg()); 101 } 102 return resultMap; 103 } 104 105 /** 106 * 判斷索引是否存在 107 * 108 * @param index 109 * @return 110 */ 111 public static boolean isIndexExist(String index) { 112 IndicesExistsResponse inExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet(); 113 return inExistsResponse.isExists(); 114 } 115 116 /** 117 * @Author: LX 118 * @Description: 判斷index下指定type是否存在 119 * @Date: 2018/11/6 14:46 120 * @Modified by: 121 */ 122 public static boolean isTypeExist(String index, String type) { 123 return isIndexExist(index) 124 ? client.admin().indices().prepareTypesExists(index).setTypes(type).execute().actionGet().isExists() 125 : false; 126 } 127 128 /** 129 * 數據添加,正定ID 130 * 131 * @param mapObj 要增長的數據 132 * @param index 索引,相似數據庫 133 * @param type 類型,相似表 134 * @param id 數據ID 135 * @return 136 */ 137 public static Map<String, Object> addData(Map<String, Object> mapObj, String index, String type, String id) { 138 IndexResponse response = client.prepareIndex(index, type, id).setSource(mapObj).get(); 139 // response.getId():就是添加數據後ES爲這條數據所生成的id 140 // 須要返回添加數據是否成功 141 String status = response.status().toString(); 142 // 添加數據後所返回的狀態(若是成功就是code:200-->OK) 143 // eq:sacii --> 小寫字母和大寫字母不同 144 // status:-->OK 145 // ok 146 if("OK".equals(status.toUpperCase())||"CREATED".equals(status.toUpperCase())) { 147 resultMap.put("code", StatusEnum.OPRATION_SUCCESS.getCode()); 148 resultMap.put("msg", StatusEnum.OPRATION_SUCCESS.getMsg()); 149 } else { 150 resultMap.put("code", StatusEnum.OPRATION_FAILED.getCode()); 151 resultMap.put("msg", StatusEnum.OPRATION_FAILED.getMsg()); 152 } 153 return resultMap; 154 } 155 156 /** 157 * 數據添加 158 * 159 * @param mapObj 要增長的數據 160 * @param index 索引,相似數據庫 161 * @param type 類型,相似表 162 * @return 163 */ 164 public static Map<String, Object> addData(Map<String, Object> mapObj, String index, String type) { 165 return addData(mapObj,index, type, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase()); 166 } 167 168 /** 169 * @author 劉其佳 170 * @description 171 * 將對象轉化爲map類型 172 * @param * param *:object 173 * @date 2019/9/19 174 * @return java.util.Map<java.lang.String,java.lang.Object> 175 * @throws 176 */ 177 public static Map<String, Object> objectTurnMap(Object object){ 178 Map<String, Object> result = new HashMap<String, Object>(); 179 //得到類的屬性名 數組 180 Field[] fields = object.getClass().getDeclaredFields(); 181 try { 182 for (Field field : fields) { 183 field.setAccessible(true); 184 String name = new String(field.getName()); 185 result.put(name, field.get(object)); 186 } 187 }catch (Exception e){ 188 e.printStackTrace(); 189 } 190 return result; 191 } 192 193 /** 194 * 經過ID刪除數據 195 * 196 * @param index 索引,相似數據庫 197 * @param type 類型,相似表 198 * @param id 數據ID 199 */ 200 public static Map<String, Object> deleteDataById(String index, String type, String id) { 201 202 DeleteResponse response = client.prepareDelete(index, type, id).execute().actionGet(); 203 if("OK".equals(response.status().toString().toUpperCase())) { 204 resultMap.put("code", StatusEnum.OPRATION_SUCCESS.getCode()); 205 resultMap.put("msg", StatusEnum.OPRATION_SUCCESS.getMsg()); 206 } else { 207 resultMap.put("code", StatusEnum.OPRATION_FAILED.getCode()); 208 resultMap.put("msg", StatusEnum.OPRATION_FAILED.getMsg()); 209 } 210 return resultMap; 211 212 } 213 214 /** 215 * 經過ID 更新數據 216 * 217 * @param mapObj 要增長的數據 218 * @param index 索引,相似數據庫 219 * @param type 類型,相似表 220 * @param id 數據ID 221 * @return 222 */ 223 public static Map<String, Object> updateDataById(Map<String, Object> mapObj, String index, String type, String id) { 224 225 UpdateRequest updateRequest = new UpdateRequest(); 226 227 updateRequest.index(index).type(type).id(id).doc(mapObj); 228 229 ActionFuture<UpdateResponse> update = client.update(updateRequest); 230 231 if("OK".equals(update.actionGet().status().toString().toUpperCase())) { 232 resultMap.put("code", StatusEnum.OPRATION_SUCCESS.getCode()); 233 resultMap.put("msg", StatusEnum.OPRATION_SUCCESS.getMsg()); 234 } else { 235 resultMap.put("code", StatusEnum.OPRATION_FAILED.getCode()); 236 resultMap.put("msg", StatusEnum.OPRATION_FAILED.getMsg()); 237 } 238 return resultMap; 239 } 240 241 /** 242 * 經過ID獲取數據 243 * 244 * @param index 索引,相似數據庫 245 * @param type 類型,相似表 246 * @param id 數據ID 247 * @param fields 須要顯示的字段,逗號分隔(缺省爲所有字段) 248 * @return 249 */ 250 public static Map<String, Object> searchDataById(String index, String type, String id, String fields) { 251 252 GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id); 253 254 if (StringUtils.isNotEmpty(fields)) { 255 getRequestBuilder.setFetchSource(fields.split(","), null); 256 } 257 258 GetResponse getResponse = getRequestBuilder.execute().actionGet(); 259 260 return getResponse.getSource(); 261 } 262 263 /** 264 * 使用分詞查詢 265 * 266 * @param index 索引名稱 267 * @param type 類型名稱,可傳入多個type逗號分隔 268 * @param query 查詢條件 269 * @param size 文檔大小限制 270 * @param fields 須要顯示的字段,逗號分隔(缺省爲所有字段) 271 * @param sortField 排序字段 272 * @param highlightField 高亮字段 273 * @return 274 */ 275 public static List<Map<String, Object>> searchListData( 276 String index, String type, QueryBuilder query, Integer size, 277 String fields, String sortField, String highlightField) { 278 279 SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index); 280 if (StringUtils.isNotEmpty(type)) { 281 searchRequestBuilder.setTypes(type.split(",")); 282 } 283 284 if (StringUtils.isNotEmpty(highlightField)) { 285 HighlightBuilder highlightBuilder = new HighlightBuilder(); 286 // 設置高亮字段 287 highlightBuilder.field(highlightField); 288 searchRequestBuilder.highlighter(highlightBuilder); 289 } 290 291 searchRequestBuilder.setQuery(query); 292 293 if (StringUtils.isNotEmpty(fields)) { 294 searchRequestBuilder.setFetchSource(fields.split(","), null); 295 } 296 searchRequestBuilder.setFetchSource(true); 297 298 if (StringUtils.isNotEmpty(sortField)) { 299 searchRequestBuilder.addSort(sortField, SortOrder.DESC); 300 } 301 302 if (size != null && size > 0) { 303 searchRequestBuilder.setSize(size); 304 } 305 306 //打印的內容 能夠在 Elasticsearch head 和 Kibana 上執行查詢 307 308 SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); 309 310 long totalHits = searchResponse.getHits().totalHits; 311 long length = searchResponse.getHits().getHits().length; 312 313 if (searchResponse.status().getStatus() == 200) { 314 // 解析對象 315 return setSearchResponse(searchResponse, highlightField); 316 } 317 return null; 318 319 } 320 321 322 /** 323 * 高亮結果集 特殊處理 324 * 325 * @param searchResponse 326 * @param highlightField 327 */ 328 private static List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) { 329 List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>(); 330 StringBuffer stringBuffer = new StringBuffer(); 331 332 for (SearchHit searchHit : searchResponse.getHits().getHits()) { 333 searchHit.getSourceAsMap().put("id", searchHit.getId()); 334 335 if (StringUtils.isNotEmpty(highlightField)) { 336 337 System.out.println("遍歷 高亮結果集,覆蓋 正常結果集" + searchHit.getSourceAsMap()); 338 Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments(); 339 340 if (text != null) { 341 for (Text str : text) { 342 stringBuffer.append(str.string()); 343 } 344 //遍歷 高亮結果集,覆蓋 正常結果集 345 searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString()); 346 } 347 } 348 sourceList.add(searchHit.getSourceAsMap()); 349 } 350 return sourceList; 351 } 352 }
注意:上述代碼中有幾處標紅的地方:
(1)工具類中有兩個添加數據的方法,緣由是:第一個添加方法在添加數據的時候指定ID
第二個添加方法在添加數據的時候隨機生成ID(即沒有指定ID)
其實添加原理都是同樣,第二個添加方法原本就是調用了第一個的添加方法進行添加
(2)在第一個添加數據的方法中,標紅的地方,原本只是進行了判斷status是否爲OK,
但我後來又加上了一個判斷是否爲CREATED,
緣由是:若是隻是添加一條數據的狀況下,添加成功的返回結果就是OK,可是我從數據庫中查出多個數據並添加進ES中,返回結果是CREATED
即可以添加成功,可是返回結果不是OK,是CREATED
五、其次咱們要注意的是service層的方法:
1 package com.aaa.liu.es.service; 2 3 import com.aaa.liu.es.mapper.UserMapper; 4 import com.aaa.liu.es.model.User; 5 import com.aaa.liu.es.utils.ESUtil; 6 import org.elasticsearch.index.query.*; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.stereotype.Service; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 11 import java.util.HashMap; 12 import java.util.Iterator; 13 import java.util.List; 14 import java.util.Map; 15 16 /** 17 * @Author 劉其佳 18 * @DateTime 2019/9/18 20:44 19 * @Project_Name SpringBootEs 20 */ 21 22 @Service 23 public class SearchService { 24 25 @Autowired 26 private UserMapper userMapper; 27 28 public static Map<String,Object> resultMap = new HashMap<String,Object>(); 29 30 /** 31 * @author 劉其佳 32 * @description 33 * 建立index 34 * @param * param *:index 35 * @date 2019/9/18 36 * @return java.util.Map<java.lang.String,java.lang.Object> 37 * @throws 38 */ 39 public Map<String,Object> createIndex(String index){ 40 return ESUtil.createIndex(index); 41 } 42 43 /** 44 * @author 劉其佳 45 * @description 46 * 刪除index 47 * @param * param *:index 48 * @date 2019/9/18 49 * @return java.util.Map<java.lang.String,java.lang.Object> 50 * @throws 51 */ 52 public Map<String,Object> deleteIndex(String index){ 53 return ESUtil.deleteIndex(index); 54 } 55 56 /** 57 * @author 劉其佳 58 * @description 59 * 向ES的索引庫添加一條數據 60 * java.lang.IllegalArgumentException: The number of object passed must be even but was [1]: 61 * 參數不合法異常 62 * 在ES的6.x版本或者以上,廢棄掉了JSON對象傳遞數據,只能用Map傳遞 63 * @param * param *: 64 * @date 2019/9/18 65 * @return java.util.Map<java.lang.String,java.lang.Object> 66 * @throws 67 */ 68 public Map<String,Object> addData(){ 69 // ES中不能再使用實體類,只能經過JSONObject對象進行傳遞數據來代替實體類 70 /* JSONObject jsonObject = new JSONObject(); 71 jsonObject.put("id", 20L); 72 jsonObject.put("username", "lisi"); 73 jsonObject.put("password", "123456"); 74 jsonObject.put("age", 30);*/ 75 Map<String,Object> dataMap=new HashMap<String, Object>(); 76 dataMap.put("id",21L); 77 dataMap.put("username","饕餮"); 78 dataMap.put("password","123456"); 79 dataMap.put("age","20"); 80 return ESUtil.addData(dataMap,"test_index3","test_type3","10102"); 81 } 82 83 /** 84 * @author 劉其佳 85 * @description 86 * 從數據庫中查詢數據 87 * 若是查到了就存入es中, 88 * 若是沒有查到就返回null; 89 * @param * param *:username 90 * @date 2019/9/19 91 * @return java.util.Map<java.lang.String,java.lang.Object> 92 * @throws 93 */ 94 public Map<String, Object> addDataBySql(String username){ 95 User user = userMapper.selectByUserName(username); 96 if(user!=null){ 97 Map<String, Object> dataMap=new HashMap<String, Object>(); 98 dataMap.put("id",user.getId()); 99 dataMap.put("username",user.getUsername()); 100 dataMap.put("password",user.getPassword()); 101 dataMap.put("age",user.getAge()); 102 return ESUtil.addData(dataMap,"test_index2","test_type2","10103"); 103 }else{ 104 resultMap.put("result","未查詢到數據"); 105 return resultMap; 106 } 107 } 108 109 /** 110 * @author 劉其佳 111 * @description 112 * 從數據庫中查詢全部數據,並放入到ES中 113 * 其中用到了工具類中的對象轉Map方法 114 * @param * param *:index 115 * @date 2019/9/19 116 * @return java.util.Map<java.lang.String,java.lang.Object> 117 * @throws 118 */ 119 public Map<String, Object> addAllData(String index){ 120 List<User> userList = userMapper.selectAll(); 121 if(userList.size()>0){ 122 for (User user : userList) { 123 Map<String , Object> mapObj=ESUtil.objectTurnMap(user); 124 resultMap = ESUtil.addData(mapObj,index,"test_type2"); 125 } 126 } 127 return resultMap; 128 } 129 130 /** 131 * @author 劉其佳 132 * @description 133 * 刪除數據 134 * @param * param *:index 135 * param *:type 136 * param *:id 137 * @date 2019/9/19 138 * @return java.util.Map<java.lang.String,java.lang.Object> 139 * @throws 140 */ 141 public Map<String, Object> deleteDataById(String id){ 142 return ESUtil.deleteDataById("test_index2", "test_type2", id); 143 } 144 145 /** 146 * @author 劉其佳 147 * @description 148 * 經過id進行查詢數據 149 * (id:是ES給這一條數據所上的索引) 150 * searchDataById:一共須要傳遞四個參數 151 * index,type,id,fields 152 * fields:傳遞所要查詢的字段(username,age) 153 * 若是須要查詢全部的字段直接傳null 154 * @param * param *:id 155 * @date 2019/9/18 156 * @return java.util.Map<java.lang.String,java.lang.Object> 157 * @throws 158 */ 159 public Map<String,Object> selectOneById(String id){ 160 return ESUtil.searchDataById("test_index2","test_type2",id,null); 161 } 162 163 /** 164 * @author 劉其佳 165 * @description 166 * 查詢全部的數據 167 * index 168 * type 169 * QueryBuilder:定義了查詢條件(是所有查詢 仍是模糊查詢 仍是分頁查詢。。。。) 170 * size:所要查詢出的條數 171 * field:所查詢的字段(若是查詢全部就直接寫null) 172 * sortField:id,age...(根據字段進行排序,若是不須要設置則傳null) 173 * highlightField:把搜索關鍵字進行高亮顯示(若是不須要則傳null) 174 * @param * param *: 175 * @date 2019/9/18 176 * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>> 177 * @throws 178 */ 179 public List<Map<String,Object>> selectAll(){ 180 //一、建立QueryBuilder對象(BoolQueryBuilder是Builder的實現類) 181 BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery(); 182 //二、建立所要搜索到額條件(查詢全部數據) 183 MatchAllQueryBuilder matchAllQueryBuilder=QueryBuilders.matchAllQuery(); 184 //三、把搜索的條件放入到BoolQueryBuilder中 185 BoolQueryBuilder must = boolQueryBuilder.must(matchAllQueryBuilder); 186 //四、返回 187 return ESUtil.searchListData("test_index2","test_type2",must,100,null,null,null); 188 } 189 190 /** 191 * @author 劉其佳 192 * @description 193 * 模糊查詢 194 * 在ES中默認若是單詞之間沒有鏈接符就會被當成一個單詞 195 * 例如zhangsan 就會被默認爲一個詞 196 * 若是須要進行模糊匹配 在ES中必需要要使用連字符(_ - =.....) 197 * 由於ES的分詞器作的不夠好,尤爲是中文(必需要整合本身的分詞器(IK),若是作得是職業搜索(用的最多的是搜狗)) 198 * IK分詞器集成很簡單,不須要任何配置 199 * IK分詞器: 200 * 在ES的服務器,在plugins目錄中建立IK文件夾(必定要大寫) 201 * 把IK分詞器解壓在IK目錄中 202 * 再次對ES文件夾進行受權 203 * @param * param *: 204 * @date 2019/9/19 205 * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>> 206 * @throws 207 */ 208 public List<Map<String,Object>> selectLikeAll(String username){ 209 //一、建立QueryBuilder對象 210 BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery(); 211 //二、建立查詢條件 212 // matchPhraseQuery有兩個參數: 213 //name:字段名字 214 //text:所須要模糊匹配的值(也就是SQL語句中like後面所匹配的值) 215 // MatchPhraseQueryBuilder matchPhraseQueryBuilder=QueryBuilders.matchPhraseQuery("username","zhang"); 216 MatchPhraseQueryBuilder matchPhraseQueryBuilder=QueryBuilders.matchPhraseQuery("username",username); 217 //三、把查詢條件放到BoolQueryBuilder對象中 218 BoolQueryBuilder must=boolQueryBuilder.must(matchPhraseQueryBuilder); 219 return ESUtil.searchListData("test_index2","test_type2",must,10,null,null,"username"); 220 } 221 222 // public void testQueryByStr(){ 223 // try { 224 // String searchStr = "陳夏天u馬立,@45"; 225 // QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchStr); 226 // 227 // // 重點是下面這行代碼 228 // builder.analyzer("myanalyzer").field("username").field("password").field("age"); 229 // Iterable<User> search = userRepository.search(builder); 230 // Iterator<User> iterator = search.iterator(); 231 // while (iterator.hasNext()){ 232 // System.out.println("---> 匹配數據: "+iterator.next()); 233 // } 234 // }catch (Exception e){ 235 // System.out.println("---> 異常信息 "+e); 236 // } 237 // } 238 }
注意:(1)在往ES中添加數據時,咱們之前使用JSON格式進行傳輸,但在ES6.x版本以上 廢棄了JSONObject,如今須要使用Map
(2)在service層中定義的模糊查詢的方法(此處使用的是ES自帶的分詞器,極其不合格,建議使用IK分詞器或者搜狗;
不過使IK分詞的話須要注意的是IK分詞器的版本要與ES版本一致(大版本和小版本上都要一致));
ES自帶的分詞器:若是有一個字段是zhangsan,咱們使用關鍵字zhang進行搜索,按理說咱們應該可以搜索到的,
但結果顯示沒有搜索到,緣由是ES自帶的分詞器將zhangsan當作了一個詞,
若是想要達到咱們想要的分詞效果,咱們須要帶上連字符,例如:zhang-san、zhang_san等
六、下面放上個人controller:
1 package com.aaa.liu.es.controller; 2 3 import com.aaa.liu.es.service.SearchService; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.web.bind.annotation.RequestMapping; 6 import org.springframework.web.bind.annotation.RestController; 7 8 import java.util.List; 9 import java.util.Map; 10 11 /** 12 * @Author 劉其佳 13 * @DateTime 2019/9/18 20:41 14 * @Project_Name SpringBootEs 15 */ 16 @RestController 17 public class SearchController { 18 19 @Autowired 20 private SearchService searchService; 21 22 /** 23 * @author 劉其佳 24 * @description 25 * 建立索引 26 * @param * param *:index 27 * @date 2019/9/18 28 * @return java.util.Map<java.lang.String,java.lang.Object> 29 * @throws 30 */ 31 @RequestMapping("/createIndex") 32 public Map<String,Object> createIndex(String index){ 33 return searchService.createIndex(index); 34 } 35 36 /** 37 * @author 劉其佳 38 * @description 39 * 刪除索引 40 * @param * param *:index 41 * @date 2019/9/18 42 * @return java.util.Map<java.lang.String,java.lang.Object> 43 * @throws 44 */ 45 @RequestMapping("/deleteIndex") 46 public Map<String,Object> deleteIndex(String index){ 47 return searchService.deleteIndex(index); 48 } 49 50 51 /** 52 * @author 劉其佳 53 * @description 54 * 向ES的索引庫中添加一條數據 55 * @param * param *: 56 * @date 2019/9/18 57 * @return java.util.Map<java.lang.String,java.lang.Object> 58 * @throws 59 */ 60 @RequestMapping("/addData") 61 public Map<String,Object> addData(){ 62 return searchService.addData(); 63 } 64 65 /** 66 * @author 劉其佳 67 * @description 68 * 從數據庫中查詢數據並存入到es中 69 * @param * param *:username 70 * @date 2019/9/19 71 * @return java.util.Map<java.lang.String,java.lang.Object> 72 * @throws 73 */ 74 @RequestMapping("/addDataBySql") 75 public Map<String, Object> addDataBySql(String username){ 76 return searchService.addDataBySql(username); 77 } 78 79 /** 80 * @author 劉其佳 81 * @description 82 * 從數據庫中查詢全部數據並放入到ES中 83 * @param * param *:index 84 * @date 2019/9/19 85 * @return java.util.Map<java.lang.String,java.lang.Object> 86 * @throws 87 */ 88 @RequestMapping("/addAllData") 89 public Map<String ,Object> addAllData(String index){ 90 return searchService.addAllData(index); 91 } 92 /** 93 * @author 劉其佳 94 * @description 95 * 根據Id刪除數據 96 * @param * param *:id 97 * @date 2019/9/19 98 * @return java.util.Map<java.lang.String,java.lang.Object> 99 * @throws 100 */ 101 @RequestMapping("/deleteDataById") 102 public Map<String, Object> deleteDataById(String id){ 103 return searchService.deleteDataById(id); 104 } 105 /** 106 * @author 劉其佳 107 * @description 108 * 經過某條數據的id進行查詢數據 109 * @param * param *:id 110 * @date 2019/9/18 111 * @return java.util.Map<java.lang.String,java.lang.Object> 112 * @throws 113 */ 114 @RequestMapping("/selectById") 115 public Map<String,Object> selectOneById(String id){ 116 return searchService.selectOneById(id); 117 } 118 119 /** 120 * @author 劉其佳 121 * @description 122 * 查詢某index、某type下的全部數據 123 * @param * param *: 124 * @date 2019/9/18 125 * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>> 126 * @throws 127 */ 128 @RequestMapping("/selectAll") 129 public List<Map<String,Object>> selectAll(){ 130 return searchService.selectAll(); 131 } 132 133 /** 134 * @author 劉其佳 135 * @description 136 * 模糊查詢 137 * @param * param *: 138 * @date 2019/9/19 139 * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>> 140 * @throws 141 */ 142 @RequestMapping("/selectLikeAll") 143 public List<Map<String,Object>> selectLikeAll(String username){ 144 return searchService.selectLikeAll(username); 145 } 146 }
七、將枚舉類放上來:
1 package com.aaa.liu.es.status; 2 3 /** 5 * @Author Seven Lee 6 * @Date Create in 2019/9/18 16:14 7 * @Description 8 **/ 9 public enum StatusEnum { 10 11 OPRATION_SUCCESS("200", "操做成功"), 12 OPRATION_FAILED("401", "操做失敗"), 13 EXIST("101", "數據存在"), 14 NOT_EXIST("402", "數據不存在"); 15 16 StatusEnum(String code, String msg) { 17 this.code = code; 18 this.msg = msg; 19 } 20 21 private String code; 22 private String msg; 23 24 public String getCode() { 25 return code; 26 } 27 28 public void setCode(String code) { 29 this.code = code; 30 } 31 32 public String getMsg() { 33 return msg; 34 } 35 36 public void setMsg(String msg) { 37 this.msg = msg; 38 } 39 }