(九)整合 ElasticSearch框架,实现高性能搜索引擎
整合 ElasticSearch框架,实现高性能搜索引擎
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。
1、SpringBoot整合ElasticSearch
1.1 核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>${spring-boot.version}</version>
</dependency>
1.2 配置文件
spring:
application:
name: ware-elastic-search
data:
elasticsearch:
# 默认 elasticsearch
cluster-name: elasticsearch
# 9200作为Http协议,主要用于外部通讯
# 9300作为Tcp协议,jar之间就是通过tcp协议通讯
cluster-nodes: 192.168.72.130:9300
1.3 实体类配置
Document 配置
加上了@Document注解之后,默认情况下这个实体中所有的属性都会被建立索引、并且分词。
indexName索引名称 理解为数据库名 限定小写
type 理解为数据库的表名称
shards = 5 默认分区数
replicas = 1 每个分区默认的备份数
refreshInterval = "1s" 刷新间隔
indexStoreType = "fs" 索引文件存储类型
源码配置
@Document(indexName = "requestlogindex",type = "requestlog")
public class RequestLog {
//Id注解Elasticsearch里相应于该列就是主键,查询时可以使用主键查询
@Id
private Long id;
private String orderNo;
private String userId;
private String userName;
private String createTime;
}
1.4 数据交互层
实现ElasticsearchRepository接口。
public interface RequestLogRepository
extends ElasticsearchRepository<RequestLog,Long> {
}
1.5 演示案例
数据增加,修改,查询,排序,多条件查询。
@Service
public class RequestLogServiceImpl implements RequestLogService {
@Resource
private RequestLogRepository requestLogRepository ;
@Override
public String esInsert(Integer num) {
for (int i = 0 ; i < num ; i++){
RequestLog requestLog = new RequestLog() ;
requestLog.setId(System.currentTimeMillis());
requestLog.setOrderNo(DateUtil.formatDate(new Date(),DateUtil.DATE_FORMAT_02)+System.currentTimeMillis());
requestLog.setUserId("userId"+i);
requestLog.setUserName("张三"+i);
requestLog.setCreateTime(DateUtil.formatDate(new Date(),DateUtil.DATE_FORMAT_01));
requestLogRepository.save(requestLog) ;
}
return "success" ;
}
@Override
public Iterable<RequestLog> esFindAll (){
return requestLogRepository.findAll() ;
}
@Override
public String esUpdateById(RequestLog requestLog) {
requestLogRepository.save(requestLog);
return "success" ;
}
@Override
public Optional<RequestLog> esSelectById(Long id) {
return requestLogRepository.findById(id) ;
}
@Override
public Iterable<RequestLog> esFindOrder() {
// 用户名倒序
// Sort sort = new Sort(Sort.Direction.DESC,"userName.keyword") ;
// 创建时间正序
Sort sort = new Sort(Sort.Direction.ASC,"createTime.keyword") ;
return requestLogRepository.findAll(sort) ;
}
@Override
public Iterable<RequestLog> esFindOrders() {
List<Sort.Order> sortList = new ArrayList<>() ;
Sort.Order sort1 = new Sort.Order(Sort.Direction.ASC,"createTime.keyword") ;
Sort.Order sort2 = new Sort.Order(Sort.Direction.DESC,"userName.keyword") ;
sortList.add(sort1) ;
sortList.add(sort2) ;
Sort orders = Sort.by(sortList) ;
return requestLogRepository.findAll(orders) ;
}
@Override
public Iterable<RequestLog> search() {
// 全文搜索关键字
/*
String queryString="张三";
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(queryString);
requestLogRepository.search(builder) ;
*/
/*
* 多条件查询
*/
QueryBuilder builder = QueryBuilders.boolQuery()
// .must(QueryBuilders.matchQuery("userName.keyword", "历张")) 搜索不到
.must(QueryBuilders.matchQuery("userName", "张三")) // 可以搜索
.must(QueryBuilders.matchQuery("orderNo", "20190613736278243"));
return requestLogRepository.search(builder) ;
}
}
2、Spring Boot 集成 Elasticsearch 实战
原文作者:武培轩
来源:微信公众号
完整代码Github仓库
Spring Boot 集成 ES 主要分为以下三步:
- 加入 ES 依赖
- 配置 ES
- 演示 ES 基本操作
2.1 加入依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.1.0</version>
</dependency>
2.2 创建ES配置
在配置文件 application.properties 中配置 ES 的相关参数,具体内容如下:
elasticsearch.host=localhost
elasticsearch.port=9200
elasticsearch.connTimeout=3000
elasticsearch.socketTimeout=5000
elasticsearch.connectionRequestTimeout=500
其中指定了 ES 的 host 和端口以及超时时间的设置,另外我们的 ES 没有添加任何的安全认证,因此 username 和 password 就没有设置。
然后在 config 包下创建 ElasticsearchConfiguration 类,会从配置文件中读取到对应的参数,接着申明一个 initRestClient 方法,返回的是一个 RestHighLevelClient,同时为它添加 @Bean(destroyMethod = “close”) 注解,当 destroy 的时候做一个关闭,这个方法主要是如何初始化并创建一个 RestHighLevelClient。
@Configuration
public class ElasticsearchConfiguration {
@Value("${elasticsearch.host}")
private String host;
@Value("${elasticsearch.port}")
private int port;
@Value("${elasticsearch.connTimeout}")
private int connTimeout;
@Value("${elasticsearch.socketTimeout}")
private int socketTimeout;
@Value("${elasticsearch.connectionRequestTimeout}")
private int connectionRequestTimeout;
@Bean(destroyMethod = "close", name = "client")
public RestHighLevelClient initRestClient() {
RestClientBuilder builder = RestClient.builder(new HttpHost(host, port))
.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder
.setConnectTimeout(connTimeout)
.setSocketTimeout(socketTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout));
return new RestHighLevelClient(builder);
}
}
2.3 定义文档实体类
首先在 constant 包下定义常量接口,在接口中定义索引的名字为 user:
public interface Constant {
String INDEX = "user";
}
然后在 document 包下创建一个文档实体类:
public class UserDocument {
private String id;
private String name;
private String sex;
private Integer age;
private String city;
// 省略 getter/setter
}
2.4 ES基本操作
在这里主要介绍 ES 的索引、文档、搜索相关的简单操作,在 service 包下创建 UserService 类。
索引操作
在这里演示创建索引和删除索引:
2.4.1 创建索引
在创建索引的时候可以在 CreateIndexRequest 中设置索引名称、分片数、副本数以及 mappings,在这里索引名称为 user,分片数 number_of_shards 为 1,副本数 number_of_replicas 为 0,具体代码如下所示:
public boolean createUserIndex(String index) throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
createIndexRequest.settings(Settings.builder()
.put("index.number_of_shards", 1)
.put("index.number_of_replicas", 0)
);
createIndexRequest.mapping("{\n" +
" \"properties\": {\n" +
" \"city\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"sex\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"age\": {\n" +
" \"type\": \"integer\"\n" +
" }\n" +
" }\n" +
"}", XContentType.JSON);
CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
return createIndexResponse.isAcknowledged();
}
通过调用该方法,就可以创建一个索引 user,索引信息如下:
2.4.2 删除索引
在 DeleteIndexRequest 中传入索引名称就可以删除索引,具体代码如下所示:
public Boolean deleteUserIndex(String index) throws IOException {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
AcknowledgedResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
return deleteIndexResponse.isAcknowledged();
}
2.5 文档操作
2.5.1 创建文档
创建文档的时候需要在 IndexRequest 中指定索引名称,id 如果不传的话会由 ES 自动生成,然后传入 source,具体代码如下:
public Boolean createUserDocument(UserDocument document) throws Exception {
UUID uuid = UUID.randomUUID();
document.setId(uuid.toString());
IndexRequest indexRequest = new IndexRequest(Constant.INDEX)
.id(document.getId())
.source(JSON.toJSONString(document), XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
return indexResponse.status().equals(RestStatus.OK);
}
下面通过调用这个方法,创建两个文档,具体内容如下:
2.5.2 批量创建文档
在一个 REST 请求中,重新建立网络开销是十分损耗性能的,因此 ES 提供 Bulk API,支持在一次 API 调用中,对不同的索引进行操作,从而减少网络传输开销,提升写入速率。
下面方法是批量创建文档,一个 BulkRequest 里可以添加多个 Request,具体代码如下:
public Boolean bulkCreateUserDocument(List<UserDocument> documents) throws IOException {
BulkRequest bulkRequest = new BulkRequest();
for (UserDocument document : documents) {
String id = UUID.randomUUID().toString();
document.setId(id);
IndexRequest indexRequest = new IndexRequest(Constant.INDEX)
.id(id)
.source(JSON.toJSONString(document), XContentType.JSON);
bulkRequest.add(indexRequest);
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
return bulkResponse.status().equals(RestStatus.OK);
}
下面通过该方法创建些文档,便于下面的搜索演示。
2.5.3 查看文档
查看文档需要在 GetRequest 中传入索引名称和文档 id,具体代码如下所示:
public UserDocument getUserDocument(String id) throws IOException {
GetRequest getRequest = new GetRequest(Constant.INDEX, id);
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
UserDocument result = new UserDocument();
if (getResponse.isExists()) {
String sourceAsString = getResponse.getSourceAsString();
result = JSON.parseObject(sourceAsString, UserDocument.class);
} else {
logger.error("没有找到该 id 的文档");
}
return result;
}
下面传入文档 id 调用该方法,结果如下所示:
2.5.4 更新文档
更新文档则是先给 UpdateRequest 传入索引名称和文档 id,然后通过传入新的 doc 来进行更新,具体代码如下:
public Boolean updateUserDocument(UserDocument document) throws Exception {
UserDocument resultDocument = getUserDocument(document.getId());
UpdateRequest updateRequest = new UpdateRequest(Constant.INDEX, resultDocument.getId());
updateRequest.doc(JSON.toJSONString(document), XContentType.JSON);
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
return updateResponse.status().equals(RestStatus.OK);
}
下面将文档 id 为 9b8d9897-3352-4ef3-9636-afc6fce43b20 的文档的城市信息改为 handan,调用方法结果如下:
2.5.5 除文档
删除文档只需要在 DeleteRequest 中传入索引名称和文档 id,然后执行 delete 方法就可以完成文档的删除,具体代码如下:
public String deleteUserDocument(String id) throws Exception {
DeleteRequest deleteRequest = new DeleteRequest(Constant.INDEX, id);
DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT);
return response.getResult().name();
}
介绍完文档的基本操作,接下来对搜索进行简单介绍:
2.5.6 搜索操作
简单的搜索操作需要在 SearchRequest 中设置将要搜索的索引名称(可以设置多个索引名称),然后通过 SearchSourceBuilder 构造搜索源,下面将 TermQueryBuilder 搜索查询传给 searchSourceBuilder,最后将 searchRequest 的搜索源设置为 searchSourceBuilder,执行 search 方法实现通过城市进行搜索,具体代码如下所示:
public List<UserDocument> searchUserByCity(String city) throws Exception {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(Constant.INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("city", city);
searchSourceBuilder.query(termQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
return getSearchResult(searchResponse);
}
该方法的执行结果如图所示:
2.5.7 聚合搜索
聚合搜索就是给 searchSourceBuilder 添加聚合搜索,下面方法是通过 TermsAggregationBuilder 构造一个先通过城市就行分类聚合,其中还包括一个子聚合,是对年龄求平均值,然后在获取聚合结果的时候,可以使用通过在构建聚合时的聚合名称获取到聚合结果,具体代码如下所示:
public List<UserCityDTO> aggregationsSearchUser() throws Exception {
SearchRequest searchRequest = new SearchRequest(Constant.INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_city")
.field("city")
.subAggregation(AggregationBuilders
.avg("average_age")
.field("age"));
searchSourceBuilder.aggregation(aggregation);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
Terms byCityAggregation = aggregations.get("by_city");
List<UserCityDTO> userCityList = new ArrayList<>();
for (Terms.Bucket buck : byCityAggregation.getBuckets()) {
UserCityDTO userCityDTO = new UserCityDTO();
userCityDTO.setCity(buck.getKeyAsString());
userCityDTO.setCount(buck.getDocCount());
// 获取子聚合
Avg averageBalance = buck.getAggregations().get("average_age");
userCityDTO.setAvgAge(averageBalance.getValue());
userCityList.add(userCityDTO);
}
return userCityList;
}
下面是执行该方法的结果:
(九)整合 ElasticSearch框架,实现高性能搜索引擎的更多相关文章
- SpringBoot2.0 整合 ElasticSearch框架,实现高性能搜索引擎
本文源码:GitHub·点这里 || GitEE·点这里 一.安装和简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful ...
- java框架之SpringBoot(13)-检索及整合Elasticsearch
ElasticSearch介绍 简介 我们的应用经常需要使用检索功能,开源的 Elasticsearch 是目前全文搜索引擎的首选.它可以快速的存储.搜索和分析海量数据.SpringBoot 通过整合 ...
- SpringBoot 2.x (12):整合Elasticsearch
Elasticsearch:一个优秀的搜索引擎框架 搜索方面最基本的是SQL的like语句 进一步的有Lucene框架 后来有企业级的Solr框架 而Elasticsearch框架尤其适合于数据量特别 ...
- Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询
摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 预见未来最好的方式就是亲手创造未来 – <史蒂夫·乔布斯传> 』 运行环境: ...
- SpringBoot整合ElasticSearch实现多版本的兼容
前言 在上一篇学习SpringBoot中,整合了Mybatis.Druid和PageHelper并实现了多数据源的操作.本篇主要是介绍和使用目前最火的搜索引擎ElastiSearch,并和Spring ...
- Spring Boot整合Elasticsearch
Spring Boot整合Elasticsearch Elasticsearch是一个全文搜索引擎,专门用于处理大型数据集.根据描述,自然而然使用它来存储和搜索应用程序日志.与Logstash和K ...
- Spring Boot 整合 elasticsearch
一.简介 我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的 首选.他可以快速的存储.搜索和分析海量数据.Spring Boot通过整合Spring Data E ...
- SpringBoot整合elasticsearch
在这一篇文章开始之前,你需要先安装一个ElasticSearch,如果你是mac或者linux可以参考https://www.jianshu.com/p/e47b451375ea,如果是windows ...
- spring-boot-starter-data-elasticsearch 整合elasticsearch 5.x详解
1.使用原因 近期公司在开发新的项目用到了elasticsearch ,因为项目框架用的spring Cloud所以依赖全用的是starter,从网上找的信息比较旧,并没有整合elasticsearc ...
随机推荐
- 事件驱动之JDK观察者模式
JDK中关于观察者模式主要了解俩个概念 Observer观察者 Observable事件源:当事件源发生某事件时,有两个事情需要注意 1.里面有一个isChange属性 当为false时不会发通知给 ...
- Flutter 基础组件:输入框和表单
前言 Material组件库中提供了输入框组件TextField和表单组件Form. 输入框TextField 接口描述 const TextField({ Key key, // 编辑框的控制器,通 ...
- [工作札记]02: .Net Winform控件TreeView最简递归绑定方法
前言:Treeview控件是我们在WinForm.WebForm开发中经常使用的控件,需要从数据库动态加载数据,然后递归绑定每一个节点:同样,递归的思路在其他程序中也经常运用,包括.Net MVC等. ...
- Java 使用 commons-fileupload 实现文件上传工具类
依赖包 文件上传可以使用 Apache 文件上传组件, commons-fileupload, 它依赖于 commons-io commons-io.jar: https://repo1.maven. ...
- 【MySQL】汇总数据 - avg()、count()、max()、min()、sum()函数的使用
第12章 汇总数据 文章目录 第12章 汇总数据 1.聚集函数 1.1.AVG()函数 avg() 1.2.COUNT()函数 count() 1.3. MAX()函数 max() 1.4.MIN() ...
- zabbix 监控的数据
/usr/local/zabbix/bin/zabbix_sender --zabbix-server 192.168.1.10 --port 10051 --input-file /var/log/ ...
- 【Linux】shell脚本实现多并发
情景 shell脚本的执行效率虽高,但当任务量巨大时仍然需要较长的时间,尤其是需要执行一大批的命令时.因为默认情况下,shell脚本中的命令是串行执行的.如果这些命令相互之间是独立的,则可以使用&qu ...
- Linux TCP漏洞 CVE-2019-11477 CentOS7 修复方法
CVE-2019-11477漏洞简单介绍 https://cert.360.cn/warning/detail?id=27d0c6b825c75d8486c446556b9c9b68 RedHat用户 ...
- CF625E Frog Fights
有\(n\)只青蛙在一个长度为\(m\)的环上打架:每只青蛙有一个初始位置\(p_i\),和一个跳跃数值\(a_i\).从\(1\)号青蛙开始按序号循环行动,每次若第\(i\)只青蛙行动,则它会向前跳 ...
- OpenCV 和 Dlib 人脸识别基础
00 环境配置 Anaconda 安装 1 下载 https://repo.anaconda.com/archive/ 考虑到兼容性问题,推荐下载Anaconda3-5.2.0版本. 2 安装 3 测 ...