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 主要分为以下三步:

  1. 加入 ES 依赖
  2. 配置 ES
  3. 演示 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框架,实现高性能搜索引擎的更多相关文章

  1. SpringBoot2.0 整合 ElasticSearch框架,实现高性能搜索引擎

    本文源码:GitHub·点这里 || GitEE·点这里 一.安装和简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful ...

  2. java框架之SpringBoot(13)-检索及整合Elasticsearch

    ElasticSearch介绍 简介 我们的应用经常需要使用检索功能,开源的 Elasticsearch 是目前全文搜索引擎的首选.它可以快速的存储.搜索和分析海量数据.SpringBoot 通过整合 ...

  3. SpringBoot 2.x (12):整合Elasticsearch

    Elasticsearch:一个优秀的搜索引擎框架 搜索方面最基本的是SQL的like语句 进一步的有Lucene框架 后来有企业级的Solr框架 而Elasticsearch框架尤其适合于数据量特别 ...

  4. Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 预见未来最好的方式就是亲手创造未来 – <史蒂夫·乔布斯传> 』 运行环境: ...

  5. SpringBoot整合ElasticSearch实现多版本的兼容

    前言 在上一篇学习SpringBoot中,整合了Mybatis.Druid和PageHelper并实现了多数据源的操作.本篇主要是介绍和使用目前最火的搜索引擎ElastiSearch,并和Spring ...

  6. Spring Boot整合Elasticsearch

    Spring Boot整合Elasticsearch   Elasticsearch是一个全文搜索引擎,专门用于处理大型数据集.根据描述,自然而然使用它来存储和搜索应用程序日志.与Logstash和K ...

  7. Spring Boot 整合 elasticsearch

    一.简介 我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的 首选.他可以快速的存储.搜索和分析海量数据.Spring Boot通过整合Spring Data E ...

  8. SpringBoot整合elasticsearch

    在这一篇文章开始之前,你需要先安装一个ElasticSearch,如果你是mac或者linux可以参考https://www.jianshu.com/p/e47b451375ea,如果是windows ...

  9. spring-boot-starter-data-elasticsearch 整合elasticsearch 5.x详解

    1.使用原因 近期公司在开发新的项目用到了elasticsearch ,因为项目框架用的spring Cloud所以依赖全用的是starter,从网上找的信息比较旧,并没有整合elasticsearc ...

随机推荐

  1. git pull 和git fetch的区别

    git pull 是上下文环境敏感的,它会把所有的提交自动给你合并到当前分支当中,没有复查的过程 而git fetch只是把拉去的提交存储到本地仓库中,真正合并到主分支中需要使用merage head ...

  2. 【Linux】中默认文本编辑器 vim 的入门与进阶

    Linux 基本操作 vim 篇 vim 简介 vim 是 Linux 上最基本的文本编辑工具,其地位像是 Windows 自带的记事本工具,还要少数的 Linux 系统自带 leafpad 编辑器, ...

  3. 使用ImmutableMap简化语句

    项目实战 最近接了一个出行权益的需求,回调的状态有十几种,需要转换为进行中,取消,已完成几种状态进行订单状态的展示,使用ImmutableMap可以简化语句,替代使用if-else 语句或者switc ...

  4. 关于 RNN 循环神经网络的反向传播求导

    关于 RNN 循环神经网络的反向传播求导 本文是对 RNN 循环神经网络中的每一个神经元进行反向传播求导的数学推导过程,下面还使用 PyTorch 对导数公式进行编程求证. RNN 神经网络架构 一个 ...

  5. Go语言从入门到放弃(设置 go get 为国内源)

    前言 Go语言学到 Gin 框架了, 其实每天学习是比较辛苦的事情, 坚持下去! 在使用 Go 过程中发现, 最无奈的是Go的一些模块下不下来, 即便挂了V, 油管2k不卡的那种, 依旧是 time ...

  6. Flutter 布局类组件:流式布局(Wrap和Flow)

    前言 把超出屏幕显示范围会自动折行的布局称为流式布局.Flutter中通过Wrap和Flow来支持流式布局,将Row换成Wrap后溢出部分则会自动折行. Wrap 接口描述 Wrap({ Key ke ...

  7. SpringCloud Alibaba Nacos服务注册与配置管理

    Nacos SpringCloud Alibaba Nacos是一个狗抑郁构建云原生应用的动态服务发现.配置管理和服务管理平台. Nacos:Dynamic Naming and Configurat ...

  8. 那些最全面的Windows10安装pytorch踩过的坑以及如何应用

    那些最全面的Windows10安装pytorch踩过的坑以及如何应用 一.pytorch简介 2017年1月,由Facebook人工智能研究院(FAIR)基于Torch推出了PyTorch.它是一个基 ...

  9. 【排序基础】5、插入排序法 - Insertion Sort

    插入排序法 - Insertion Sort 文章目录 插入排序法 - Insertion Sort 插入排序设计思想 插入排序代码实现 操作:插入排序与选择排序的比较 简单记录-bobo老师的玩转算 ...

  10. 【Linux】CentOS7中修改中文字符集

    CentOS 7中字符集查看的方式是 locale -a   或者locale 如果想显示中文的话,应该修改为 LANG="zh_CN.UTF-8" 在命令行界面临时修改字符集的话 ...