SpringBoot(7) ------>整合Elasticsearch

1、向pom文件添加依赖

      <!--SpringBoot 默认使用spring-boot-starter-data-elasticsearch-->
        <!-- elasticsearch -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

2、application.yml添加配置

spring:
  data:
    elasticsearch:
      repositories:
        enabled: true
      cluster-nodes: 127.0.0.1:9300 
      cluster-name: es 
      client:
        reactive:
          socket-timeout: 5000

3、model层

  1)Role

@Data
@EqualsAndHashCode(callSuper = false)
public class Role implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 角色名
     */
    private String roleName;

    /**
     * 角色编号
     */
    private String roleCode;

    /**
     * 角色介绍
     */
    private String introduce;

}

  2)EsRole

**
 * @author liangd
 * date 2020-12-18 09:38
 * code
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Document(indexName = "role",shards = 2,replicas = 1)
public class EsRole implements Serializable {
    /**
     * Shard=1:存储到第一个切片
     * replicas =0: 不备份
     * FieldType.Keyword:存储数据时候,不会分词建立索引
     * FieldType.Text:存储数据时候,会自动分词,并生成索引
     *
     *ik_max_word与ik_smart区别?
     * ik_max_word
     * 会将文本做最细粒度的拆分,比如会将“*人民大会堂”拆分为“*、中华人民、中华、华人、
     * 人民*、人民、*、大会堂、大会、会堂等词语。
     * ik_smart
     * 会做最粗粒度的拆分,比如会将“*人民大会堂”拆分为*、人民大会堂。
     *
     */
    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 角色名
     */
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String roleName;

    /**
     * 角色编号
     */
    @Field(type = FieldType.Keyword)
    private String roleCode;

    /**
     * 角色介绍
     */
    private String introduce;

}

4、接口层

  EsService

/**
 * @author liangd
 * date 2020-12-18 09:49
 * code
 */
public interface EsRoleService {
    /**
     * 从数据库中导入所有角色到ES
     */
    int importAll();

    /**
     * 根据id删除
     */
    void delete(Integer id);

    /**
     * 根据关键字搜索名称或者副标题
     */
    Page<EsRole> search(String keyword, Integer pageNum, Integer pageSize);

//    void deleteById(Long id);
//
//    Page esRoleService(String keyword, Integer pageNum, Integer pageSize);

    /**
     * 高亮搜索
     * @param keyword
     * @return
     */
    SearchHits searchHit(String keyword);

    /**
     * 高亮搜索
     * @param roleName
     * @return CommonResult
     */
    CommonResult transferSearchHit(String roleName);
}

5、接口实现层

  新建EsServiceImpl

package com.donleo.elastic.service.impl;

import com.donleo.elastic.common.CommonResult;
import com.donleo.elastic.mapper.RoleMapper;
import com.donleo.elastic.model.Role;
import com.donleo.elastic.repository.EsRoleRepository;
import com.donleo.elastic.service.EsRoleService;
import com.donleo.elastic.vo.EsRole;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.matchQuery;

/**
 * @author liangd
 * date 2020-12-18 09:53
 * code 数据与es交互
 */
@Service
public class EsRoleServiceImpl implements EsRoleService {

    @Autowired
    private EsRoleRepository esRoleRepository;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private ElasticsearchRestTemplate restTemplate;


    @Override
    public int importAll() {

        List<Role> roleList = roleMapper.selectList(null);
        //将roleList里面的数据浅拷贝到es中
        List<EsRole> collect = roleList.stream().map(role -> {
            EsRole esRole = new EsRole();
            BeanUtils.copyProperties(role, esRole);
            return esRole;
        }).collect(Collectors.toList());
        //方式一
//        collect.forEach(esRoleRepository::save);
        //方式二
        esRoleRepository.saveAll(collect);
        return roleList.size();
    }

    @Override
    public void delete(Integer id) {
        EsRole esRole = new EsRole();
        esRole.setId(id);
        esRoleRepository.delete(esRole);
    }

    @Override
    public Page<EsRole> search(String keyword, Integer pageNum, Integer pageSize) {
        NativeSearchQuery roleName = new NativeSearchQueryBuilder()
                .withQuery(matchQuery("roleName", keyword)).build();
        return esRoleRepository.search(roleName);
    }

    @Override
    public SearchHits searchHit(String keyword) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(matchQuery("roleName", keyword))
                .withHighlightFields(
                        new HighlightBuilder.Field("roleName")
                                .preTags("<font style='color:red'>").postTags("</font>")
                ).build();
        return restTemplate.search(query, EsRole.class);
    }

    /**
     *
     * @param roleName  高亮显示的字段
     * @return
     */
    @Override
    public CommonResult transferSearchHit(String roleName) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(matchQuery("roleName", roleName))
                .withHighlightFields(
                        new HighlightBuilder.Field("roleName")
                                .preTags("<font style='color:red'>").postTags("</font>")
                ).build();
        SearchHits<EsRole> search = restTemplate.search(query, EsRole.class);
        List<EsRole> collect = tansferSearchHitToEsRole(search);

        return CommonResult.success(collect);
    }

    /**
     * 1、获取searchHits
     * 2、获取content
     * 3、获取highlightFields
     * 4、利用反射将highlightFields的字段值赋值给context的字段值
     * 5、用collect将map对象收集起来转换为集合
     * @param search
     * @return
     */
    private List<EsRole> tansferSearchHitToEsRole(SearchHits<EsRole> search){
        List<SearchHit<EsRole>> searchHits = search.getSearchHits();
        List<EsRole> collect = searchHits.stream().map(searchHit -> {
            EsRole content = searchHit.getContent();
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            highlightFields.forEach((k, v) -> {
                StringBuilder temp = new StringBuilder();
                for (String value : v) {
                    temp.append(value);
                }
                String s = temp.toString();
                try {
                    Field keyField = EsRole.class.getDeclaredField(k);
                    keyField.setAccessible(true);
                    keyField.set(content, s);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            return content;
        }).collect(Collectors.toList());
        return collect;
    }
}

6、持久层

package com.donleo.elastic.repository;

import com.donleo.elastic.vo.EsRole;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @author liangd
 * date 2020-12-18 09:46
 * code
 */
public interface EsRoleRepository extends ElasticsearchRepository<EsRole,Integer> {

}

7、控制层

package com.donleo.elastic.controller;


import com.donleo.elastic.common.CommonResult;
import com.donleo.elastic.model.Role;
import com.donleo.elastic.service.EsRoleService;
import com.donleo.elastic.service.RoleService;
import com.donleo.elastic.vo.EsRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author liangd
 * @since 2020-12-18
 */
@RestController
@RequestMapping("/role")
public class RoleController {

    @Autowired
    private RoleService roleService;

    @Autowired
    private EsRoleService esRoleService;

    @GetMapping("/findAll")
    public CommonResult findAll(){
        List<Role> list = roleService.list();
        return CommonResult.success(list);
    }

    /**
     * 导入es
     * @return
     */
    @GetMapping("/importEsAll")
    public CommonResult importEsAll(){
        int result = esRoleService.importAll();
        return CommonResult.success(result);
    }

    /**
     * 高亮搜索
     * @return  searchHits
     */
    @GetMapping("/searchHit")
    public CommonResult searchHit(String roleName){
        SearchHits searchHits = esRoleService.searchHit(roleName);
        return CommonResult.success(searchHits);
    }

    /**
     * 高亮搜索
     * 只返回esRolemodel数据
     * @return CommonResult
     */
    @GetMapping("/transferSearchHit")
    public CommonResult transferSearchHit(String roleName){
        return esRoleService.transferSearchHit(roleName);
    }

    /**
     * 分页搜索 //待完善
     * @return  Page<EsRole>
     */
    @GetMapping("/searchPage")
    public CommonResult searchPage(String roleName,Integer pageNum,Integer pageSize){
        Page<EsRole> search = esRoleService.search(roleName, pageNum, pageSize);
        return CommonResult.success(search);
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @DeleteMapping("/deleteEs")
    public CommonResult deleteEs(@RequestParam Integer id){
        esRoleService.delete(id);
        return CommonResult.success(1);
    }
}

 

上一篇:Springboot之日志错误信息定位


下一篇:mall整合Swagger-UI实现在线API文档