Fork me on GitHub

springboot整合ES

(2020/4/19对本文进行补充)关于springboot整个es有四种方法,分别是TransportClient、RestClient、SpringData-Es、Elasticsearch-SQL。

官方推荐的是RestClient,我在工作中见到的是SpringData-ES,这里举的例子是TransportClient。

也就是说 ↓ ↓ ↓

如果是TransportClient,可以参考这篇文章。

如果使用的是RestClient,可以参考这篇文章:https://www.jianshu.com/p/2ff05a83816e;这种方式也是官网推荐的;

如果使用的是SpringData-Es,可以参考:https://blog.csdn.net/tianyaleixiaowu/article/details/76149547/ (介绍了ElasticsearchRepoistory和ElasticsearchTemplate两种方法的具体使用。);

如果使用的是Elasticsearch-SQL,面向百度,我确实太懒了,

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 }

 

posted @ 2019-09-19 21:43  秋刀  阅读(22089)  评论(3编辑  收藏  举报