Spring Boot 集成Elasticsearch7.x

本文档介绍了如何在SpringBoot2.x项目中集成Elasticsearch7.9.3,配置相关依赖,创建学生实体类,并通过ElasticsearchRestTemplate进行索引的创建、删除、存在性检查以及文档的保存、查询、删除等操作。同时,展示了如何进行复杂的查询,包括多条件查询、高亮显示、排序和分页。
摘要由CSDN通过智能技术生成

环境:Spring Boot 2.x、 Elasticsearch7.9.3、jdk1.8

1、创建Spring Boot项目

2、pom文件(注意Springboot与es版本对应)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.es</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>es-demo</name>
    <description>ES测试Demo</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- ElasticSearch -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

        <!-- swagger2 配置 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.6</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.11</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3、配置文件 application.yml

spring:
  elasticsearch:
    rest:
      uris: http://127.0.0.1:9200
      read-timeout: 40s
      connection-timeout: 10s

4、以学生为例,新建 Stu

package com.es.demo.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.util.List;

/**
 * @author a1234
 */
@Data
@Document(indexName = "stu",createIndex = false)
@ApiModel(value="stu", description="学生")
public class Stu {

    @Id
    @ApiModelProperty(value = "主键ID")
    private Long id;

    @ApiModelProperty(value = "姓名")
    @Field(type = FieldType.Text)
    private String name;

    @ApiModelProperty(value = "年龄")
    @Field(type = FieldType.Integer)
    private Integer age;

    @ApiModelProperty(value = "爱好")
    @Field(type = FieldType.Keyword)
    private List<String> hobbys;

    @ApiModelProperty(value = "家庭住址")
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String addr;
}

5、Controller

package com.es.demo.controller;


import com.es.demo.pojo.Stu;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author a1234
 * 索引操作
 */
@Api(tags = "index-api")
@RestController
@RequestMapping("/index")
public class IndexController {

    private final ElasticsearchRestTemplate elasticsearchRestTemplate;

    public IndexController(ElasticsearchRestTemplate elasticsearchRestTemplate) {
        this.elasticsearchRestTemplate = elasticsearchRestTemplate;
    }

    @RequestMapping(value = "/create-index", method = RequestMethod.POST)
    @ApiOperation("创建索引")
    public Object createEsIndex() {
        boolean index = elasticsearchRestTemplate.indexOps(Stu.class).create();
        System.out.println("创建索引结果是" + index);
        return true;
    }

    @RequestMapping(value = "/delete-index", method = RequestMethod.POST)
    @ApiOperation("删除索引")
    public Object deleteEsIndex() {
        boolean deleteIndex = elasticsearchRestTemplate.indexOps(Stu.class).delete();
        System.out.println("删除索引结果是" + deleteIndex);
        return deleteIndex;
    }

    @RequestMapping(value = "/exist-index", method = RequestMethod.POST)
    @ApiOperation("是否存在索引")
    public Object existEsIndex() {
        boolean existsIndex = elasticsearchRestTemplate.indexOps(Stu.class).exists();
        System.out.println("是否存在的结果是" + existsIndex);
        return existsIndex;
    }

}
package com.es.demo.controller;


import com.es.demo.pojo.Stu;
import com.es.demo.pojo.vo.StuVo;
import com.es.demo.repository.StuRepository;
import com.es.demo.utils.PageResult;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
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.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author a1234
 */
@Api(tags = "stu-api")
@RestController
@RequestMapping("/stu")
public class StuController {

    private final ElasticsearchRestTemplate elasticsearchRestTemplate;

    private final StuRepository stuRepository;

    public StuController(StuRepository stuRepository, ElasticsearchRestTemplate elasticsearchRestTemplate) {
        this.stuRepository = stuRepository;
        this.elasticsearchRestTemplate = elasticsearchRestTemplate;
    }

  

    @RequestMapping(value = "/save-doc", method = RequestMethod.POST)
    @ApiOperation("保存文档")
    public Stu saveEsDoc(@RequestBody Stu stu) {
        Stu result = stuRepository.save(stu);
        return result;
    }

    @RequestMapping(value = "/query-doc", method = RequestMethod.GET)
    @ApiOperation("根据名字查询文档")
    @ApiImplicitParam(name = "name", value = "名称", required = true,dataType = "String", paramType = "query")
    public List<Stu> queryByName(String name) {
        List<Stu> result = stuRepository.queryStuByName(name);
        return result;
    }

    @RequestMapping(value = "/exist-doc", method = RequestMethod.GET)
    @ApiOperation("判断文档是否存在")
    @ApiImplicitParam(name = "id", value = "id", required = true,dataType = "Long", paramType = "query")
    public Object existDoc(Long id) {
        return stuRepository.existsById(id);
    }

    @RequestMapping(value = "/queryById-doc", method = RequestMethod.GET)
    @ApiOperation("根据id查询文档")
    @ApiImplicitParam(name = "id", value = "id", required = true,dataType = "Long", paramType = "query")
    public Object queryById(Long id) {
        Optional<Stu> optionalStu = stuRepository.findById(id);
        return optionalStu;
    }

    @RequestMapping(value = "/delete-doc", method = RequestMethod.POST)
    @ApiOperation("根据id删除文档")
    @ApiImplicitParam(name = "id", value = "id", required = true,dataType = "Long", paramType = "query")
    public Object deleteDoc(Long id) {
        stuRepository.deleteById(id);
        return true;
    }


    // -- -- -- -- -- 复杂查询  -- -- -- -- --

    @RequestMapping(value = "/query-doc/complex", method = RequestMethod.POST)
    @ApiOperation("多条件查询")
    public PageResult queryByName(@RequestBody Stu stu) {
        String addr = stu.getAddr();
        List<String> hobbyList = stu.getHobbys();
        String name = stu.getName();

        // 先构建查询条件
        BoolQueryBuilder defaultQueryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.isNotBlank(addr)){
            defaultQueryBuilder.should(QueryBuilders.matchQuery("addr", addr));
        }
        if (StringUtils.isNotBlank(name)){
            defaultQueryBuilder.should(QueryBuilders.termQuery("name", name));
        }
        if (!CollectionUtils.isEmpty(hobbyList)){
            for (String hobby : hobbyList) {
                defaultQueryBuilder.must(QueryBuilders.termQuery("hobbys", hobby));
            }
        }

        // 分页条件
        PageRequest pageRequest = PageRequest.of(0,5);
        // 高亮条件
        HighlightBuilder highlightBuilder = getHighlightBuilder("addr", "hobbys");
        // 排序条件
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("age").order(SortOrder.DESC);
        //组装条件
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(defaultQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(pageRequest)
                .withSort(sortBuilder).build();

        //数据查询
        SearchHits<Stu> searchHits = elasticsearchRestTemplate.search(searchQuery, Stu.class);

        // 高亮字段映射
        List<StuVo> stuVoList = Lists.newArrayList();
        for (SearchHit<Stu> searchHit : searchHits) {
            Stu content = searchHit.getContent();
            StuVo StuVo = new StuVo();
            BeanUtils.copyProperties(content,StuVo);
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            for (String highlightField : highlightFields.keySet()) {
                if (StringUtils.equals(highlightField,"hobbys")){
                    StuVo.setHobbys(highlightFields.get(highlightField));
                }else if(StringUtils.equals(highlightField,"addr")){
                    StuVo.setAddr(highlightFields.get(highlightField).get(0));
                }
            }
            stuVoList.add(StuVo);
        }
        // 组装分页对象
        PageResult page = new PageResult();
        page.setRows(stuVoList);
        page.setPage(pageRequest.getPageNumber()+1);
        page.setTotal((int) ((searchHits.getTotalHits()  +  pageRequest.getPageSize()  - 1) / pageRequest.getPageSize()));
        page.setRecords(searchHits.getTotalHits());
        return page;
    }

    /**
     * 设置高亮字段
     * @param fields
     * @return
     */
    private HighlightBuilder getHighlightBuilder(String... fields) {
        //生成高亮查询器
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        for (String field : fields) {
            //高亮查询字段
            highlightBuilder.field(field);
        }
        //如果要多个字段高亮,这项要为false
        highlightBuilder.requireFieldMatch(false);
        //高亮设置
        highlightBuilder.preTags("<span style=\"color:red\">");
        highlightBuilder.postTags("</span>");
        //下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
        //最大高亮分片数
        highlightBuilder.fragmentSize(800000);
        //从第一个分片获取高亮片段
        highlightBuilder.numOfFragments(0);
        return highlightBuilder;
    }

}

6、repository

package com.es.demo.repository;

import com.es.demo.pojo.Stu;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public interface StuRepository extends ElasticsearchRepository<Stu,Long> {

    List<Stu> queryStuByName(String name);

}
package com.es.demo.utils;

import lombok.Data;

import java.util.List;

/**
 * 用来返回分页的数据格式
 * @author a1234
 */
@Data
public class PageResult {

	/**
	 * 当前页数
	 */
	private int page;

	/**
	 * 总页数
	 */
	private int total;

	/**
	 * 总记录数
	 */
	private long records;

	/**
	 * 每行显示的内容
	 */
	private List<?> rows;


}

7、打开 Swagger页面 测试

8、

添加成功

条件查询

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值