官网
Spring Data Elasticsearch基于Spring Data API简化 Elasticsearch 操作,将原始操作Elasticsearch 的客户端API进行封装。Spring Data为Elasticsearch 项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储索引库数据访问层。
spring-data-elasticsearch与ES、SpringBoot的对应关系
Spring Data通过注解来声明字段的映射属性,有下面的三个注解:
- @Document 作用在类,标记实体类为文档对象,一般有两个属性
indexName:对应索引库名称
type:对应在索引库中的类型
shards:分片数量,默认5
replicas:副本数量,默认1 - @Id 作用在成员变量,标记一个字段作为id主键
- @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
type:字段类型,取值是枚举:FieldType
index:是否索引,布尔类型,默认是true
store:是否存储,布尔类型,默认是false
analyzer:分词器名称
本文使用的是:
spring-boot(2.3.12.RELEASE)
spring-data-elasticsearch(2.3.12.RELEASE)
- 导入依赖
spring-data-elasticsearch
org.springframework.boot spring-boot-starter-data-elasticsearch
全部pom
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.12.RELEASE com.example ES-test 0.0.1-SNAPSHOT ES-test ES-test 1.8 org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-elasticsearch org.projectlombok lombok org.apache.logging.log4j log4j-core 2.8.2 junit junit 4.12 org.springframework.boot spring-boot-maven-plugin
- 配置文件
##单机版连接 ##spring.elasticsearch.rest.uris=http://127.0.0.1:9200 ##集群版连接 spring.elasticsearch.rest.uris= http://127.0.0.1:9200,http://127.0.0.1:9201,http://127.0.0.1:9202 spring.elasticsearch.rest.read-timeout= 30 spring.elasticsearch.rest.connection-timeout= 30
- 创建索引
请求地址:http://localhost:9200/blog
请求类型:PUT
请求体:
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"id":{
"type":"long"
},
"title": {
"type": "text"
},
"content": {
"type": "text"
},
"author":{
"type": "text"
},
"category":{
"type": "keyword"
},
"createTime": {
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||epoch_millis"
},
"updateTime": {
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss.SSS||yyyy-MM-dd'T'HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||epoch_millis"
},
"status":{
"type":"integer"
},
"serialNum": {
"type": "keyword"
}
}
}
}
- 编写实体类
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "blog", shards = 1, replicas = 1)
public class Blog {
//此项作为id,不会写到_source里边。
@Id
private Long blogId;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String content;
@Field(type = FieldType.Text)
private String author;
//博客所属分类。
@Field(type = FieldType.Keyword)
private String category;
//0: 未发布(草稿) 1:已发布 2:已删除
@Field(type = FieldType.Integer)
private int status;
//序列号,用于给外部展示的id
@Field(type = FieldType.Keyword)
private String serialNum;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
@Field(type= FieldType.Date, format= DateFormat.custom, pattern="yyyy-MM-dd HH:mm:ss.SSS")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
@Field(type=FieldType.Date, format=DateFormat.custom, pattern="yyyy-MM-dd HH:mm:ss.SSS")
private Date updateTime;
}
- 编写Dao
import com.example.estest.bean.Blog; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface BlogRepository extends ElasticsearchRepository{ }
- 增删改查
import com.example.estest.bean.Blog;
import com.example.estest.dao.BlogRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("crud")
public class CrudController {
@Autowired
private BlogRepository blogRepository;
@GetMapping("addDocument")
public Blog addDocument() {
Long id = 1L;
Blog blog = new Blog();
blog.setBlogId(id);
blog.setTitle("我是一个大标题" + id);
blog.setContent("这是添加单个文档的实例" + id);
blog.setAuthor("wf");
blog.setCategory("ElasticSearch");
blog.setCreateTime(new Date());
blog.setStatus(1);
blog.setSerialNum(id.toString());
blog.setUpdateTime(new Date());
return blogRepository.save(blog);
}
@GetMapping("findById")
public Blog findById(Long id) {
return blogRepository.findById(id).get();
}
@GetMapping("addDocuments")
public Object addDocuments(Integer count) {
List blogs = new ArrayList<>();
for (int i = 1; i <= count; i++) {
Long id = (long)i;
Blog blog = new Blog();
blog.setBlogId(id);
blog.setTitle("我是一个大标题" + id);
blog.setContent("这是博客内容" + id);
blog.setAuthor("wf");
blog.setCategory("ElasticSearch");
blog.setCreateTime(new Date());
blog.setStatus(1);
blog.setSerialNum(id.toString());
blogs.add(blog);
}
return blogRepository.saveAll(blogs);
}
@GetMapping("editDocument")
public Blog editDocument(Long id) {
Blog blog = new Blog();
blog.setBlogId(id);
blog.setTitle("Spring Data ElasticSearch学习教程" + id);
blog.setContent("这是修改单个文档的实例" + id);
return blogRepository.save(blog);
}
@GetMapping("deleteDocument")
public String deleteDocument(Long id) {
blogRepository.deleteById(id);
return "success";
}
@GetMapping("deleteDocumentAll")
public String deleteDocumentAll() {
blogRepository.deleteAll();
return "success";
}
@GetMapping("queryAll")
public Object queryAll() {
return blogRepository.findAll();
}
@GetMapping("findByPageable/{page}/{size}")
public List findByPageable(@PathVariable("page") Integer page, @PathVariable("size") Integer size){
//设置排序(排序方式,正序还是倒序,排序的 id)
Sort sort = Sort.by(Sort.Direction.DESC,"blogId");
//设置查询分页
PageRequest pageRequest = PageRequest.of(page, size,sort);
//分页查询
Page productPage = blogRepository.findAll(pageRequest);
System.out.println("总页数:"+productPage.getTotalPages());
System.out.println("分页参数信息:"+productPage.getPageable());
System.out.println("总条数:"+productPage.getTotalElements());
System.out.println("当前页码:"+productPage.getNumber());
System.out.println("单页展示条数:"+productPage.getNumberOfElements());
System.out.println("排序字段及方式:"+productPage.getSort());
System.out.println("当前集合总数:"+productPage.getSize());
return productPage.getContent();
}
}
- 自定义查询方法及高亮查询
跟Spring Data JPA类似,spring data elsaticsearch提供了自定义方法的查询方式,
在Repository接口中自定义方法,spring data根据方法名,自动生成实现类,但是方法名必须符合一定的规则,
官网方法名规则
在自定义的Dao中编写如下方法:
import com.example.estest.bean.Blog; import org.springframework.data.elasticsearch.annotations.Highlight; import org.springframework.data.elasticsearch.annotations.HighlightField; import org.springframework.data.elasticsearch.annotations.HighlightParameters; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.util.List; public interface BlogRepository extends ElasticsearchRepository{ @Highlight(fields = { @HighlightField(name = "title") }) List > findByTitle(String title); @Highlight(fields = { @HighlightField(name = "content") }, parameters = @HighlightParameters( preTags = "", postTags = "" )) List > findByContent(String content); @Highlight( fields = { @HighlightField(name = "title"), @HighlightField(name = "content") }, parameters = @HighlightParameters( preTags = "", postTags = "" )) List > findByTitleAndContent(String title, String content); }
编写接口:
import com.example.estest.bean.Blog;
import com.example.estest.dao.BlogRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("crud")
public class CrudController {
@Autowired
private BlogRepository blogRepository;
……
此处省略上文接口
……
@GetMapping("highlightQueryTitle/{title}")
public List> highlightQueryTitle(@PathVariable("title") String title) {
return blogRepository.findByTitle(title);
}
@GetMapping("highlightQueryContent/{content}")
public List> highlightQueryContent(@PathVariable("content") String content) {
return blogRepository.findByContent(content);
}
@GetMapping("highlightQueryTitleAndContent/{title}/{content}")
public List> highlightQueryTitleAndContent(@PathVariable("title") String title,@PathVariable("content") String content) {
return blogRepository.findByTitleAndContent(title,content);
}
}
- 高亮查询效果
- 自定义DSL查询
跟JPA一样,Spring Data ElasticSearch可以使用@Query自定义语句进行查询。
但Spring Data ElasticSearch不能通过冒号指定参数(比如:title),只能用问号加序号,比如?0)
在自定义的Dao中编写如下方法:
import com.example.estest.bean.Blog; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.annotations.Highlight; import org.springframework.data.elasticsearch.annotations.HighlightField; import org.springframework.data.elasticsearch.annotations.HighlightParameters; import org.springframework.data.elasticsearch.annotations.Query; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.data.repository.query.Param; import java.util.List; public interface BlogRepository extends ElasticsearchRepository{ ……………… ………此处省略前文内容……… ……………… @Query("{"bool":{"must":[{"match":{"title":"?0"}}," + "{"match":{"content":"?1"}}]}}") List findByTitleAndContentCustom(@Param("title") String title, @Param("content") String content); @Query("{"bool":{"must":[{"match":{"title":"?0"}}," + "{"match":{"content":"?1"}}]}}") Page findByTitleAndContentCustom(@Param("title") String title, @Param("content") String content,Pageable pageable); }
编写接口:
import com.example.estest.bean.Blog;
import com.example.estest.dao.BlogRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("crud")
public class CrudController {
@Autowired
private BlogRepository blogRepository;
………………
………此处省略前文内容………
………………
@GetMapping("listByTitleAndContent/{title}/{content}")
public List listByTitleAndContent(@PathVariable("title") String title,@PathVariable("content") String content) {
return blogRepository.findByTitleAndContentCustom(title, content);
}
@GetMapping("pageByTitleAndContent/{title}/{content}")
public Page pageByTitleAndContent(@PathVariable("title") String title,@PathVariable("content") String content) {
PageRequest pageRequest = PageRequest.of(0, 2);
return blogRepository.findByTitleAndContentCustom(title, content, pageRequest);
}
}
- 测试



