1、新建一个maven项目
2、导入相应的jar包
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.CountRequestBuilder
3、开始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 //1、创建TransportClient对象 43 TransportClient transportClient=null; 44 try{ 45 //2、设置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 //3、初始化TransportClient对象 51 transportClient=new PreBuiltTransportClient(settings); 52 //4、配置对ES的连接信息 53 TransportAddress transportAddress=new TransportAddress(InetAddress.getByName(esProperties.getIp()),Integer.parseInt(esProperties.getPort())); 54 //5、把对ES的连接对象放到transportClient对象中 55 transportClient.addTransportAddress(transportAddress); 56 }catch (UnknownHostException e){ 57 e.printStackTrace(); 58 } 59 return transportClient; 60 } 61 }
4、主要的核心其实在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
5、其次我们要注意的是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 //1、创建QueryBuilder对象(BoolQueryBuilder是Builder的实现类) 181 BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery(); 182 //2、创建所要搜索到额条件(查询所有数据) 183 MatchAllQueryBuilder matchAllQueryBuilder=QueryBuilders.matchAllQuery(); 184 //3、把搜索的条件放入到BoolQueryBuilder中 185 BoolQueryBuilder must = boolQueryBuilder.must(matchAllQueryBuilder); 186 //4、返回 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 //1、创建QueryBuilder对象 210 BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery(); 211 //2、创建查询条件 212 // matchPhraseQuery有两个参数: 213 //name:字段名字 214 //text:所需要模糊匹配的值(也就是SQL语句中like后面所匹配的值) 215 // MatchPhraseQueryBuilder matchPhraseQueryBuilder=QueryBuilders.matchPhraseQuery("username","zhang"); 216 MatchPhraseQueryBuilder matchPhraseQueryBuilder=QueryBuilders.matchPhraseQuery("username",username); 217 //3、把查询条件放到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等
6、下面放上我的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 }
7、将枚举类放上来:
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 }