最近系统中要用到搜索功能,如果直接使用MySQL的like查询语句会影响系统的性能,所以就采用了Elasticsearch
来实现站内搜索。
本文以图书的搜索功能作为Demo来演示在Spring Boot如何整合Elasticsearch
以及如何优雅的使用elasticsearch。
Spring Boot与Elasticsearch的对应版本
Elasticsearch
更新非常快,最新的7.x版本已经不支持自定义类型了,默认以 “_doc
“ 作为类型,一个索引只能有一个类型。
为了避免使用的Elasticsearch
版本和SpringBoot采用的版本不一致导致的问题,尽量使用一致的版本。下表是对应关系:

创建SpringBoot项目并引入Elasticsearch依赖
-
本文使用的SpringBoot版本为2.3.7.RELEASE -
对应的 Elasticsearch
版本为7.6.2
引入Spring-Data-Elasticsearch
依赖,Spring 团队将Elasticsearch
归到“Data”的范畴,所以依赖是以Spring-Data开头。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
这个例子中还使用了JPA,所以需要引入JPA依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
基于Java的Elasticsearch配置
新建类 RestClientConfig
作为Elasticsearch Rest
客户端的配置了类:
/**
* ElasticSearch 客户端配置
*
* @author geng
*/
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
注意:Elasticsearch
从7版本开始TransportClient
已经过时了不再推荐使用,将在8.0版本删除,具体参考:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html
Spring Data Elasticsearch
支持TransportClient
,只要它在已使用的Elasticsearch
版本中可用,但从4.0版本起已经不再建议使用它。
强烈建议使用Hight Level Rest Client
(也就是上边的配置)代替TransportClient
。
像操作普通数据库一样实现Elasticsearch的CRUD
说真的看到这,你是不是惊呆了,反正我是!Spring Boot提供高级接口,操作ElasticSearch
就像写数据库的CRUD一样简单!大佬,请收下我的膝盖!
编码流程和数据库CRUD一样:
定义Book实体,官方叫Elasticsearch
对象映射:
import lombok.Data;
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;
/**
* @author geng
*/
@Data
@Document(indexName = "book",createIndex = true)
public class Book {
@Id
@Field(type = FieldType.Text)
private String id;
@Field(analyzer="ik_max_word")
private String title;
@Field(analyzer="ik_max_word")
private String author;
@Field(type = FieldType.Double)
private Double price;
@Field(type = FieldType.Date,format = DateFormat.basic_date_time)
private Date createTime;
@Field(type = FieldType.Date,format = DateFormat.basic_date_time)
private Date updateTime;
}
-
@Document定义在 Elasticsearch
中索引信息 -
@Id定义了Elasticsearch的_id -
@Field定义字段类型等信息 -
…更多注解请参照官方文档…
Elasticsearch Repositories
创建接口ESBookRepository
import com.gyb.elasticsearch.demo.entity.es.Book;
import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* ES Book repository
*
* @author geng
*/
public interface ESBookRepository extends ElasticsearchRepository<Book, String> {
List<Book> findByTitleOrAuthor(String title, String author);
@Highlight(fields = {
@HighlightField(name = "title"),
@HighlightField(name = "author")
})
@Query("{"match":{"title":"?0"}}")
SearchHits<Book> find(String keyword);
}
该接口继承了ElasticsearchRepository
接口,ElasticsearchRepository
接口定义了Elasticsearch
的CRUD,继承了该接口的接口甚至无需定义任何其他的方法就能满足基本需求。
比较厉害的是通过定义的方法名就能自动创建各种查询,例如:
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
* 关系型数据库mysql Repository
*
* @author cloudgyb
*/
public interface BookRepository extends JpaRepository<Book, String> {
List<Book> findByNameAndPrice(String name, Integer price);
}
这个方法将自动被转化成下面的Elasticsearch Json
查询语句
{
"query": {
"bool" : {
"must" : [
{ "query_string" : { "query" : "?", "fields" : [ "name" ] } },
{ "query_string" : { "query" : "?", "fields" : [ "price" ] } }
]
}
}
}
好NB有没有?
并且支持使用@Query
注解自定义查询,使用@Highlight
定义关键字高亮,没有一个注解解决不了的问题。
方法名支持的关键字如下:


这只是部分,更多查看官方文档。
并且方法支持多种返回类型,无需做任何适配,根据类型自动封装:
-
List -
Stream -
SearchHits -
List<SearchHit>
-
Stream<SearchHit>
-
SearchPage
定义Service方法
/**
* @author geng
*/
@Slf4j
@Service
public class BookService {
private final BookRepository bookRepository;
private final ESBookRepository esBookRepository;
private final TransactionTemplate transactionTemplate;
public BookService(BookRepository bookRepository,
ESBookRepository esBookRepository,
TransactionTemplate transactionTemplate) {
this.bookRepository = bookRepository;
this.esBookRepository = esBookRepository;
this.transactionTemplate = transactionTemplate;
}
public void addBook(Book book) {
final Book saveBook = transactionTemplate.execute((status) ->
bookRepository.save(book)
);
final com.gyb.elasticsearch.demo.entity.es.Book esBook = new com.gyb.elasticsearch.demo.entity.es.Book();
assert saveBook != null;
BeanUtils.copyProperties(saveBook, esBook);
esBook.setId(saveBook.getId() + "");
try {
esBookRepository.save(esBook);
}catch (Exception e){
log.error(String.format("保存ES错误!%s", e.getMessage()));
}
}
public List<com.gyb.elasticsearch.demo.entity.es.Book> searchBook(String keyword){
return esBookRepository.findByTitleOrAuthor(keyword, keyword);
}
public SearchHits<com.gyb.elasticsearch.demo.entity.es.Book> searchBook1(String keyword){
return esBookRepository.find(keyword);
}
}
定义Controller
/**
* @author geng
*/
@RestController
public class BookController {
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
@PostMapping("/book")
public Map<String,String> addBook(@RequestBody Book book){
bookService.addBook(book);
Map<String,String> map = new HashMap<>();
map.put("msg","ok");
return map;
}
@GetMapping("/book/search")
public SearchHits<com.gyb.elasticsearch.demo.entity.es.Book> search(String key){
return bookService.searchBook1(key);
}
}
测试看效果
1、启动Elasticsearch服务
无需手动创建Book索引,Springboot启动自动创建
2、启动SpringBoot项目
3、使用/book接口创建几条测试数据
curl -H "Content-Type:application/json" -XPOST http://localhost:8080/book -d
{
"id":"1",
"title":"富婆通讯录",
"author":"耿小李",
"price":9999.9,
"createTime":"2020-12-21 12:00:00"
}
4、搜索数据
打开浏览器http://localhost:8080/book/search?key=富婆
:

Spring Data Elasticsearch
官方文档:
https://docs.spring.io/spring-data/elasticsearch/docs/4.1.2/reference/html/#preface
GITHUB仓库源码:
https://github.com/cloudgyb/es-spring-boot
来源:cloudgyb.blog.csdn.net/article/details/111469217 精彩推荐 最全的java面试题库 开源版的高仿 “ 微信 ”,吊炸天! 与其在网上拼命找题? 不如马上关注我们~
↓点阅读原文,Java面试题库尽情看!
原文始发于微信公众号(Java面试题精选):全网超详细的 SpringBoot 整合 Elasticsearch 实战教程
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/54227.html