与SpringBoot集成
- 初始化
Sprint-boot
工程,引入elasticsearch
包,本篇文章中的spring-boot
的版本为2.2.13.RELEASE
,通过下面的方式引入elasticsearch
包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
- 文件配置,新版本的Elasticsearch只需要在
application.yml
中加入下面的配置
spring:
elasticsearch:
rest:
uris: http://localhost:9201 # es配置,如果是集群则需要配置多个
- 通过上面两步就完成了spring和elasticsearch的集成,
操作Elasticsearch的API
配置Document
先要配置实体和ES的映射,通过在实体类中加入注解的方式来自动映射跟索引,我这里是配置了product
索引和实体的映射
@Data
@Document(indexName = "product", type = "_doc")
public class ClusterEsProduct {
@Id
private Long id;
@Field(type = FieldType.Long)
private Long prodId;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String prodName;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String prodDesc;
@Field(type = FieldType.Float)
private Float price;
@Field(type = FieldType.Integer)
private Integer stock;
@Field(type = FieldType.Date)
private Date createDate;
private String prodDescHighlight;
}
- 有了上面的实体映射就可以通过下面的两种方式来查询ES中的数据,具体方式如下
方式一ElasticsearchRestTemplate
- 在Spring启动的时候自动注入了该Bean,它封装了操作
Elasticsearch
的增删改查API,这个比较好理解,像Spring封装的JDBCTemplate
、redisTemplate
,这个功能也基本类似,屏蔽下层的API,提供简单易用的操作。下面就是使用它的分页功能的一个例子,实现了查询,排序,高亮,分页的功能
// 引入ElasticsearchRestTemplate
@Autowired
private ElasticsearchRestTemplate esRestTemplate;
public AggregatedPage<ClusterEsProduct> findByPage(String prodName) {
// 完全匹配查询条件
MatchQueryBuilder matchQueryBuilder1 = new MatchQueryBuilder("prod_desc", prodName);
// 排序
FieldSortBuilder price = SortBuilders.fieldSort("price").order(SortOrder.ASC);
// 高亮显示
HighlightBuilder highlightBuilder
= new HighlightBuilder().field("prod_desc").postTags("</red>").preTags("<red>");
// 分页
PageRequest pageRequest = PageRequest.of(0, 2);
// 查询条件
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(matchQueryBuilder1);
// 组装上述查询条件
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
.withSort(price)
.withHighlightBuilder(highlightBuilder)
.withPageable(pageRequest)
.build();
return esRestTemplate.queryForPage(searchQuery, ClusterEsProduct.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
// 改造返回的结果
if (null != searchResponse.getHits()) {
// 获取命中的记录
SearchHit[] hits = searchResponse.getHits().getHits();
if (null != hits && hits.length > 0) {
List<ClusterEsProduct> productVoList = Lists.newArrayList();
Arrays.asList(hits).forEach(product -> {
Map<String, Object> source = product.getSourceAsMap();
ClusterEsProduct productVo = JSON.parseObject(JSON.toJSONString(source), ClusterEsProduct.class);
Map<String, HighlightField> highlightFieldMap = product.getHighlightFields();
if (CollectionUtil.isNotEmpty(highlightFieldMap)) {
// 设置高亮显示
productVo.setProdDescHighlight(highlightFieldMap.get("prod_desc").getFragments()[0].toString());
}
productVoList.add(productVo);
});
return new AggregatedPageImpl<>((List<T>) productVoList,
pageable,
searchResponse.getHits().getTotalHits());
} else {
log.info("没有命中记录");
}
}
return null;
}
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
return null;
}
});
}
方式二ElasticsearchRepository
- 这个是一个接口,类似于MyBatis的
Mapper
接口。该接口有两种方式来实现查询:一种是通过注解@Query
,另外一种是通过findByxxx
的方式
@Repository
public interface ClusterEsProductRepository extends ElasticsearchRepository<ClusterEsProduct, Long> {
/**
* 根据名称来查询
* @param stock
* @return
*/
List<ClusterEsProduct> findClusterEsProductByStockGreaterThan(Integer stock);
/**
* 根据描述查询
* @param prod_desc
* @return
*/
@Query(value = "{\"match\":{\"prod_desc\":\"?0\"}}")
List<ClusterEsProduct> queryByProdDesc(String prod_desc);
}
- 生成接口的方式
总结
- 通过把Elasticsearch集成到Spring中来,能够灵活的使用Elasticsearch的API,归根结底,Spring的API也是基于
DSL
来编写,所以还是对底层的操作API比较熟悉。通过上面的介绍,操作的方式有两种,一种是通过ElasticsearchRestTemplate
,另外一种是通过ElasticsearchRepository
,可以根据自己的需要决定采用哪一种。