zoukankan      html  css  js  c++  java
  • 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 }

    乾坤未定,你我皆是黑马
  • 相关阅读:
    Git push 出现 refusing to merge unrelated histories
    The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.
    Linux离线安装docker&docker-compose
    mybatis新增记录使用 useGeneratedKeys无法返回主键
    Docker 修改容器内的时区
    快排写法
    c++学生信息管理系统(window控制台实现鼠标点击操作)
    洛谷P1006 传纸条(多维DP)
    二维bit模板
    一个milller_rabin模板
  • 原文地址:https://www.cnblogs.com/liuqijia/p/11552795.html
Copyright © 2011-2022 走看看