环境: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、
添加成功
条件查询