先来简单看看ElasticSearch的应用场景和基本特性:
Elasticsearch是基于Apache Lucene的一个分布式的、开源的搜索分析引擎,支持各种数据类型,包括文本、数字、地理、结构化、非结构化,可通过RESTFul风格的API的形式实现对数据的操作。
主要功能和特性
- 分布式的搜索引擎和数据分析引擎
- 全文检索,结构化检索,数据分析
- 对海量数据进行近实时的处理
- 支持横向扩展集群便捷的构建大型分布式系统
ElasticSearch的部署以及head插件的安装
关于部署和基本操作请移步到我的有道云笔记参考
这里我们重点介绍与SpringBoot的集成,使用ElasticsearchRepository和elasticsearchTemplate结合的方式访问ElasticSearch,为什么要结合的方式了,因为ElasticsearchRepository操作虽然很便捷,但是有些API还不够丰富,可结合这两种方式来操作
SpringBoot集成ElasticSearch
- maven主要配置
<!--elasticSearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
- application-dev.yml文件的配置
application-dev.yml是开发环境用的配置文件,需要在application.yml指定使用的当前配置文件,这种方式非常便捷,值得借鉴。
server:
port: 8082
tomcat:
max-threads: 1000
servlet:
context-path: /elastic/
spring:
data:
elasticsearch:
cluster-nodes: 192.168.3.1:9300
cluster-name: myes
repositories:
enabled: true
192.168.3.1:9300是单机节点,集群环境用逗号分割多个,注意这里要使用9300不是9200
3.创建实体类,使用注解的方式和ElasticSearch中的结构化索引字段对应起来,SpringBoot启动时会根据实体类自动创建结构化索引
/**
* @Author: wangjianzhong
* @Description:
* @Date: Create in 11:27 2020/3/12
*/
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Document(indexName = "vehicle_report",type = "distance")
public class Distance implements Serializable {
@Field(type = FieldType.Keyword)
private String fleetName;
@Field(type = FieldType.Keyword)
private String vehicleName;
@Field(type = FieldType.Keyword)
private String vehicleData;
}
@Document(indexName = “vehicle”,type = “distance”)
对应索引名称为vehicle,类型为distance
4. DAO层(ElasticsearchRepository方式)
@Repository
public interface DistanceDaoRepository extends ElasticsearchRepository<Distance,String> {
/**
* 通过名字查询,不用写具体实现,Pageable 是支持分页的参数
* @param fleet
* @param pageable
* @return
*/
List<Distance> queryDistanceByFleet(String fleetName Pageable pageable) throws Exception;
// 相当于sql中的in,直接以函数名做具体查询的实现
List<Distance> queryDistanceByFleetIn(Collection<String> fleet,Pageable pageable) throws Exception;
//使用SearchQuery构建复杂的查询
@Override
Page<Distance> search(SearchQuery searchQuery);
}
- Service层
@Service
@Log4j2
public class ReportServiceImpl implements ReportService {
@Autowired
private DistanceDaoRepository distanceDaoRepository;
/*@Override
public Map<String, Object> findDistance(String fleetName) throws Exception {
Pageable pageable = PageRequest.of(paramBean.getPageNow(), paramBean.getPageSize());
Map<String, Object> resultMap = new HashMap<>();
List<Distance> distanceList = distanceDaoRepository.queryDistanceByFleet(
fleetName,
pageable
);
resultMap.put("dataList", distanceList);
return resultMap;
}
}
}
- 这里conroller层不在介绍,重点在看以下其它高级查询
// 范围查询,相当于sql中的between
RangeQueryBuilder rqb = QueryBuilders.rangeQuery("currentDate")
.gte("2019-03-15")
.lte("2019-04-15");
// 布尔查询 matchPhraseQuery是短语匹配
BoolQueryBuilder bqb = QueryBuilders.boolQuery();
//must 是必须匹配,可以多个相连接相当于sql中的and
bqb.must(QueryBuilders.matchPhraseQuery("vehicleVin", "lvbxxx")
// 模糊查询,相当于sq中的like
WildcardQueryBuilder wqb = QueryBuilders.wildcardQuery("vehicleVin","lvbxxx"+"*");
// in和not in 参数传list,库中字段类型如果为text,termsQuery会默认做分词处理,字段类型为keyword时才不会被分词
bqb.must(QueryBuilders.termsQuery("brand", "A","B"));
// 排序查询
FieldSortBuilder fsb =SortBuilders.fieldSort("drivingDistance").order(SortOrder.ASC);
// NativeSearchQueryBuilder组装查询条件
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(bqb)
.withSort(fsb)
.withPageable(pageable)
.build();
- 聚合查询(这里使用elasticsearchTemplate的方式)
//聚合查询
TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_fieldName").field("fieldName");
//聚合查询Dao层
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Override
public Aggregations pullDownMenu(SearchQuery searchQuery) throws Exception {
return elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
@Override
public Aggregations extract(SearchResponse searchResponse) {
return searchResponse.getAggregations();
}
});
}
//聚合查询结果解析service层
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(bqb)
.addAggregation(termsAggregationBuilder)
.build();
Aggregations aggregations = queryForElasticsearchTemplate.pullDownMenu(searchQuery);
Terms term = aggregations.get("group_" + menuName);
for (Terms.Bucket bk : term.getBuckets()) {
resultList.add(bk.getKeyAsString());
}
先写到这里,以上代码只展示部分,供核心API使用参考。