springboot10-检索
检索功能
- 简介
- 我们的应用经常需要添加检索功能, 开源的ElasticSearch是目前全文搜索引擎的首选. 他可以快速存储, 搜索, 和分析海量数据, SpringBoot通过整合Spring Data ElasticSearch为我们提供了非常便捷的检索功能支持.
-
Elasticsearch是一个分布式搜索服务, 提供Restful API, 底层基于Lucene, 采用多shard(分片)的方式保证数据安全, 并且提供自动resharding的功能, github等大型的站点也是采用了ElasticSearch作为其搜索服务.
- 安装Elasticsearcch
- 以docker的方式
docker pull elasticsearch:7.7.1
docker run -d -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" --name es01 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" 镜像ID
- 简单使用
- ES是面向文档的, 意味着它存储整个对象或文档, 同时, 索引每个文档的内容使之可以被检索.
- 在ES中, 使用JSON作为文档的序列化格式.
- 如一个User对象
- 如一个User对象
- 简单操作
- 存储雇员数据, 以雇员文档的形式存储, 存储数据到ES的行为叫做索引. 但在索引一个文档之前, 需要确定将文档存储到哪.
- ES集群中可以有多个索引, 每个索引可包含多个类型, 每个类型可包含多个文档, 而每个文档之间又可以有多个属性.
- 对于雇员目录, 做如下操作
- 每个雇员索引一个文档, 包含该雇员的所有信息.
- 每个文档都是employee类型
- 该类型位于索引megacors内.
- 该索引保存在我们的ES集群中
PUT /megacorp/employee/1 { "first_name" : "john", "last_name" : "Smith", "age" : 25, "about" : "I love to go rock climbing", "interests" : ["sports", "music"] } megacorp是索引名称 employee是类型名称 1代表特定雇员的ID
- 检索时只需发GET /megacorp/employee/1
- 同理, 发DELETE请求是删除, 发HEAD请求来检查是不是有这个员工
- 若要更新已存在的文档, 只需再次PUT.
- 这里的版本会叠加, 同时result : "updated"
- 存储雇员数据, 以雇员文档的形式存储, 存储数据到ES的行为叫做索引. 但在索引一个文档之前, 需要确定将文档存储到哪.
- 搜索功能
- 查询所有员工
GET /megacorp/employee/_search
- 按条件查找
GET /megacorp/employee/_search?q=last_name:Smith
- 查询表达式
- 全文检索
- ES中的检索并非像传统数据库那样内容必须严格一致才能搜出来, 而有一个字段叫相关性得分, 得分越高, 则字段越相近.
- 短语搜索(严格匹配)
- 需用到"match_phrase"
{ "query" : { "match_phrase" : { "about" : "rock climbing" } } }
- 需用到"match_phrase"
- 高亮搜索
{ "query" : { "match_phrase" : { "about" : "rock climbing" } }, "highlight" : { "fields" : { "about" : {} } } }
- 查询所有员工
SpringBoot整合ElasticSearch
- 依赖
- 导入依赖
- SpringBoot默认支持两种技术与ES交互
<!--SpringBoot默认使用SpringData ElasticSearch模块进行操作--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> 或者 <dependency> <groupId>io.searchbox</groupId> <artifactId>jest</artifactId> <version>6.3.1</version> </dependency>
- Jest
- 不导入第二个依赖不会生效.
- SpringData ElasticSearch
- Client 节点信息(clusterNodes, clusterName)
- ElasticsearchTemplate 操作ES
- 编写一个ElasticsearchRepository的子接口来操作ES
- Jest
- 使用Jest操作ES
- 配置: application.properties
spring.elasticsearch.jest.uris=http://192.168.13.129:9200/
- 测试
- bean信息
public class Article { @JestId //主键 private Integer id; private String auth; private String title; private String content; //... }
- 测试
@Autowired private JestClient jestClient; //测试添加 @Test public void contextLoads() { //1. 给ES中索引一个文档 Article article = new Article(); article.setId(1); article.setTitle("好消息"); article.setAuth("zhangsan"); article.setContent("Hello world"); //构建一个索引功能 Index index = new Index.Builder(article).index("yellowstreak").type("news").build(); try { //执行 jestClient.execute(index); } catch (IOException e) { e.printStackTrace(); } } //测试搜索 @Test public void search() { //查询表达式 String json = "{\n" + "\t\"query\" : {\n" + "\t\t\"match\" : {\n" + "\t\t\t\"content\" : \"hello\"\n" + "\t\t}\n" + "\t}\n" + "}"; //构建搜索功能 Search search = new Search.Builder(json).addIndex("yellowstreak").addType("news").build(); //执行 try { SearchResult result = jestClient.execute(search); System.out.println(result.getJsonString()); } catch (IOException e) { e.printStackTrace(); } }
- bean信息
- 整合SpringData ES模块
- 注意: 目前spring-data-elasticsearch支持6.x版本, 不支持7.x版本.
- 版本不匹配会报错
NoNodeAvailableException None of the configured nodes are available
- 版本不匹配会报错
- 配置
spring.data.elasticsearch.cluster-name=docker-cluster spring.data.elasticsearch.cluster-nodes=192.168.13.129:9300
- 用法
- bean
@Document(indexName = "yellowstreak", type = "book") public class Book { private Integer id; private String bookName; private String author; //... }
- 编写一个ElasticsearchRepository的子接口
public interface BookRepository extends ElasticsearchRepository<Book, Integer> { //自定义命名方法名 public List<Book> finByBookNameLike(String bookName);
- 测试
@Autowired private BookRepository bookRepository; @Test public void test02() { Book book = new Book(); book.setId(1); book.setBookName("西游记"); book.setAuthor("吴承恩"); bookRepository.index(book); List<Book> books = bookRepository.finByBookNameLike("游"); }
- bean