此文适合了解了es相关概念以及基础知识的同学阅读
Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful风格的http接口。
简单来说,es主要是用来做搜索的,比如像商城网站中(商品、店铺……)的搜索、小说网站中(书名、作者……)的搜索。
我们要知道,任何一门新的技术、框架、中间件出来肯定是为了解决一些问题。es的诞生就是为了在Lucene的基础上更好的帮助我们解决传统搜索的问题。
最原始、传统的搜索功能都是基于db表的模糊查询,这样做有很大的局限性
es帮我们解决了上面的问题,它作为一个专业搜索的中间件,对于查询搜索方面肯定跟redis做缓存一样,完全没问题。
这里介绍SpringBoot如何集成es来使用。像目前主流的一些开源中间件技术,Spring家族都帮我们集成进去了。使用起来很方便
系统:windows 10
elasticsearch官网下载地址
下载好对应的windows版本,解压到任意工作目录,es的安装非常方便,解压即用。
刚下载的es默认的分词器只能分解英文,对于中文不太友好。所以我们需要为es下载安装IK分词器
IK分词器下载:
Ik分词器下载地址,分词器下载跟es版本对应的就行。下载好后解压zip包
在你下载的es安装路径下的plugins文件夹下创建一个ik的文件夹,然后将上面解压出来的分词器内容复制到创建的ik文件夹下面。下面图ik分词器官方安装说明
效果如下
ik分词器的安装就完成了,而后回答es根目录下的bin目录里,双击启动es
当es正常启动,且启动过程出现下面情况时,说明ik分词器已经正常安装好可以使用了
1、新建springboot项目,引入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
dependency>
RestHighLevelClient配置
@Configuration
public class EsConfig {
@Bean
public RestHighLevelClient highLevelClient(){
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
2、在你的数据库实体类里每个字段加上相应的注解即可(跟Jpa一样)
@Data
@Document(indexName = "book")
//es默认会自动创建索引,你可以把document理解为数据库中的行,index理解为数据库中的表,以前在index和document之间还有个type对应数据库中的表概念。后面es7之后将type去掉了,所以这里就简单把index当作一个表的概念去理解
public class Book {
@Id
@Field(type = FieldType.Long)//type表示存到es当中的数据类型
private Long id;
@Field(type = FieldType.Text,analyzer = "ik-max-word")
private String bookName;//analyzer 表示选择分词器
@Field(type = FieldType.Text,analyzer = "ik-max-word")
private String bookDesc;
@Field(type = FieldType.Text)
private String type;
@Field(type = FieldType.Integer)
private Integer status;
@Field(analyzer = "ik-max-word")
private String author;
@Field(type = FieldType.Text)
private String tag;
@Field(type = FieldType.Date,format = DateFormat.basic_date_time)
private LocalDateTime createTime;
@Field(type = FieldType.Text)
private String createBy;
@Field(type = FieldType.Date,format = DateFormat.basic_date_time)
private LocalDateTime updateTime;
}
由于spring官方对es的高度封装,我们已经可以做到像操作数据库一样操作es了
以上面的Book对象举例,创建接口EsBooksRepository,继承Spring封装的ElasticsearchRepository,ElasticsearchRepository提供了一些简单的操作es方法
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.data.elasticsearch.repository;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.lang.Nullable;
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID> extends PagingAndSortingRepository<T, ID> {
/** @deprecated */
@Deprecated
default <S extends T> S index(S entity) {
return this.save(entity);
}
/** @deprecated */
@Deprecated
<S extends T> S indexWithoutRefresh(S entity);
/** @deprecated */
@Deprecated
Iterable<T> search(QueryBuilder query);
/** @deprecated */
@Deprecated
Page<T> search(QueryBuilder query, Pageable pageable);
/** @deprecated */
Page<T> search(Query searchQuery);
Page<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable);
/** @deprecated */
@Deprecated
void refresh();
}
到这一步,就已经可以简单的使用了。可以在其他地方直接将创建的EsBooksRepository这个接口注入使用。比如我测试方便,直接在controller里使用
保存或者更新时,先存db后操作es。
上面说到集成了spring-boot-starter-data-elasticsearch后,用法上跟Jpa一样,我们可以在自己创建的EsBooksRepository里自定义根据方法名查询对应的条件
简单的查询根据方法名定义就能实现,比如说我需要查询的是多条数据,那我就选findBooksBy……,如果需要查询1条就选findBookBy
findXXBy后面接条件,方法名定义了几个条件,就需要传几个参数
定义好调用的时候,直接将前端传递的搜索值所有参数塞一遍就好了
//这里定义了两个查询条件:书名和作者,直接将搜索值传递给定义好的方法就行
List<Book> booksByBookNameAndAuthor = esBookRepository.findBooksByBookNameOrAuthor(nameAndAuthor,nameAndAuthor);
测试结果:查询条件值是“我的”,结果返回所有书名和作者名含有“我的”两个字的book对象
高亮查询需要设置一些地方,下面是高亮查询的简单demo。
/**
* 书名、作者搜索
*/
@RequestMapping(method = RequestMethod.GET, value = {"/book/search" })
public RestResponse<List<Book>> search(@RequestParam String nameAndAuthor){
BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
//匹配两个高亮字段:书名、作者
queryBuilder.should(QueryBuilders.matchQuery("bookName",nameAndAuthor))
.should(QueryBuilders.matchQuery("author",nameAndAuthor));
//设置查询高亮样式preTags、postTags
//高亮查询其实就是给相应需要高亮显示的字段加个自定义样式
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withHighlightFields(new HighlightBuilder.Field("bookName")
,new HighlightBuilder.Field("author"))
.withHighlightBuilder(new HighlightBuilder().preTags("").postTags(""))
.build();
SearchHits<Book> search = elasticsearchRestTemplate.search(query, Book.class);
List<SearchHit<Book>> searchHits = search.getSearchHits();
//查询返回结果,将高亮字段重新赋值给相应book对象,以便返回前端展示
List<Book> collect = searchHits.stream().map(
bookSearchHit -> {
Book content = bookSearchHit.getContent();
List<String> bookName = bookSearchHit.getHighlightField("bookName");
List<String> author = bookSearchHit.getHighlightField("author");
if (!CollectionUtils.isEmpty(bookName)){
content.setBookName(bookName.get(0));
}
if (!CollectionUtils.isEmpty(author)){
content.setAuthor(author.get(0));
}
return content;
}
).collect(Collectors.toList());
return RestResponse.success(collect);
}
结果:可以看到返回的数据中,“我的”这两个字都添加了高亮样式,放到前端html展示就是红字字体
以上就是springboot集成es后的一个简单使用,spring封装过后的spring-boot-starter-data-elasticsearch使用起来还是非常方便简单的。