• Elasticsearch连接方式有两种;分别为TCP协议HTTP协议

最近使用es比较多,之前使用一直是使用spring封装的spring-data-elasticsearch;关于spring-data-elasticsearch有以下几点比较难受:

  • 基于TCP协议的使用(不确定是否支持http, 公司XX云大佬推荐使用HTTP协议,好像是官方推荐?)

  • 版本对应比较恶心人

  • 不好用

  • 基于以上几点,索性抛弃spring-data-elasticsearch,自己造轮子;

  • 根据 官方文档 描述,我们选择使用RestHighLevelClient来实现es基础查询;


官方描述:

The Java REST Client comes in 2 flavors:

Java Low Level REST Client: the official low-level client for Elasticsearch. It allows to communicate with an Elasticsearch cluster through http. Leaves requests marshalling and responses un-marshalling to users. It is compatible with all Elasticsearch versions.

Java High Level REST Client: the official high-level client for Elasticsearch. Based on the low-level client, it exposes API specific methods and takes care of requests marshalling and responses un-marshalling.

  • 提供Java Low Level REST Client 版本和 Java High Level REST Client 版本:

    • Java Low Level REST Client 与所有Elasticsearch版本兼容(版本问题舒服)
    • 通过HTTP协议与Elasticsearch集群进行通信(大佬推荐)
    • Java High Level REST Client 是基于Java Low Level REST Client 版本实现更多高级API
  • 很显然我们选择RestHighLevelClient


Spring整合RestHighLevelClient

  1. 构建ElasticsearchClient
  • 查看RestHighLevelClient构造器可以发现可以使用RestClientBuilder来构建,简单demo如下
    /**
* 连接超时时间
*/
private final static int CONNECT_TIMEOUT = 5000;
/**
* 连接超时时间
*/
private final static int SOCKET_TIMEOUT = 40000;
/**
* 获取连接的超时时间
*/
private final static int CONNECTION_REQUEST_TIMEOUT = 1000;
/**
* 最大连接数
*/
private final static int MAX_CONNECT_NUM = 100;
/**
* 最大路由连接数
*/
private final static int MAX_CONNECT_ROUTE = 100; @Bean(name = "elasticsearchClient", destroyMethod = "close")
public RestHighLevelClient client() {
RestClientBuilder builder = RestClient.builder(new HttpHost("host", "port", "http"));
// 配置一些请求配置的参数
builder.setRequestConfigCallback(requestConfigBuilder -> {
requestConfigBuilder.setConnectTimeout(CONNECT_TIMEOUT);
requestConfigBuilder.setSocketTimeout(SOCKET_TIMEOUT);
requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT);
return requestConfigBuilder;
});
// 配置一些httpClient的参数
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setMaxConnTotal(MAX_CONNECT_NUM);
httpClientBuilder.setMaxConnPerRoute(MAX_CONNECT_ROUTE);
return httpClientBuilder;
});
builder.setFailureListener(new RestClient.FailureListener(){
@Override
public void onFailure(HttpHost host) {
// TODO do something when failed
super.onFailure(host);
}
});
return new RestHighLevelClient(builder);
}
  • 支持一些回调与参数的配置,具体的API可自行查看RestClientBuilder的源码
  • 配置完client后我们可以使用client造一些简单的轮子, 如es默认查询只可以查询1000条数据,我们可以封装查询所有数据
    public List<SearchHit> searchAll(SearchRequest searchRequest) {
try {
List<SearchHit> hits = new ArrayList<>(16);
int maxNum = searchRequest.source().size();
searchRequest.scroll(TimeValue.timeValueMinutes(10));
SearchResponse search = client.search(searchRequest);
hits.addAll(Arrays.asList(search.getHits().getHits()));
while (search.getHits().getHits().length == maxNum) {
SearchScrollRequest searchScrollRequest = new SearchScrollRequest(search.getScrollId());
searchScrollRequest.scroll(TimeValue.timeValueMinutes(10));
search = client.searchScroll(searchScrollRequest);
hits.addAll(Arrays.asList(search.getHits().getHits()));
}
return hits;
} catch (IOException e) {
log.error("Get message error.", e);
return null;
}
}
  • 有了以上接口,我们可以查询一些常用数据,如以下为查询数据的简单使用:
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
boolBuilder.filter(QueryBuilders.termQuery("type", 0));
boolBuilder.filter(QueryBuilders.termsQuery("id.keyword", id)); RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("createTime");
rangeQueryBuilder.gte(startTime);
rangeQueryBuilder.lte(endTime);
boolBuilder.filter(rangeQueryBuilder); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(9999);
sourceBuilder.fetchSource(new String[]{"field1", "field2", "field3"}, new String[]{});
sourceBuilder.query(boolBuilder); SearchRequest searchRequest = new SearchRequest("index");
searchRequest.source(sourceBuilder);
List<SearchHit> searchHits = repository.searchAll(searchRequest);
  • 具体API使用可查看官方文档

更新于2019-10-28

IndexRequest indexRequest = new IndexRequest(index, type, id);
indexRequest.source(entityMapper.mapToString(map), Requests.INDEX_CONTENT_TYPE);
return client.index(indexRequest);
  • 官方API中IndexRequest提供以下几种source方法:

    • 值得注意的是source(Map source)source(Map source, XContentType contentType) 方法,对于Map的传参,会进行类型校验;
    • 源码如下:
     public IndexRequest source(Map source, XContentType contentType) throws ElasticsearchGenerationException {
    try {
    XContentBuilder builder = XContentFactory.contentBuilder(contentType);
    builder.map(source);
    return source(builder);
    } catch (IOException e) {
    throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e);
    }
    }
  • 其中builder.map中的unknownValue方法会遍历参数进行逐一校验:

  • 源码如下:

   private XContentBuilder map(Map<String, ?> values, boolean ensureNoSelfReferences) throws IOException {
if (values == null) {
return this.nullValue();
} else {
if (ensureNoSelfReferences) {
ensureNoSelfReferences(values);
} this.startObject();
Iterator var3 = values.entrySet().iterator(); while(var3.hasNext()) {
Entry<String, ?> value = (Entry)var3.next();
this.field((String)value.getKey());
this.unknownValue(value.getValue(), false);
} this.endObject();
return this;
}
}
  • 检验方法源码
    private void unknownValue(Object value, boolean ensureNoSelfReferences) throws IOException {
if (value == null) {
this.nullValue();
} else {
XContentBuilder.Writer writer = (XContentBuilder.Writer)WRITERS.get(value.getClass());
if (writer != null) {
writer.write(this, value);
} else if (value instanceof Path) {
this.value((Path)value);
} else if (value instanceof Map) {
Map<String, ?> valueMap = (Map)value;
this.map(valueMap, ensureNoSelfReferences);
} else if (value instanceof Iterable) {
this.value((Iterable)value, ensureNoSelfReferences);
} else if (value instanceof Object[]) {
this.values((Object[])value, ensureNoSelfReferences);
} else if (value instanceof ToXContent) {
this.value((ToXContent)value);
} else {
if (!(value instanceof Enum)) {
throw new IllegalArgumentException("cannot write xcontent for unknown value of type " + value.getClass());
} this.value(Objects.toString(value));
} }
}
  • 为了避免这个坑,可以使用jsonString来规避,具体使用如下:
	IndexRequest indexRequest = new IndexRequest(index, type, id);
indexRequest.source(JSON.toJSONString(map), Requests.INDEX_CONTENT_TYPE);
client.index(indexRequest);

Spring与RestHighLevelClient的更多相关文章

  1. springboot使用RestHighLevelClient批量插入

    1.引入maven(注意版本要一致) <dependency> <groupId>org.springframework.boot</groupId> <ar ...

  2. elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    一.ES Client 简介 1. ES是一个服务,采用C/S结构 2. 回顾 ES的架构 3. ES支持的客户端连接方式 3.1 REST API ,端口 9200 这种连接方式对应于架构图中的RE ...

  3. Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介.Java REST Client.Java Client.Spri ...

  4. elasticsearch RestHighLevelClient 使用方法及封装工具

    目录 EsClientRHL 更新日志 开发原因: 使用前你应该具有哪些技能 工具功能范围介绍 工具源码结构介绍 开始使用 未来规划 git地址:https://gitee.com/zxporz/ES ...

  5. ElasticSearch使用RestHighLevelClient进行搜索查询

    Elasticsearch Java API有四类client连接方式:TransportClient.  RestClient .Jest. Spring_Data_Elasticsearch.其中 ...

  6. ElasticSearch RestHighLevelClient 通用操作

    项目中使用到ElasticSearch作为搜索引擎.而ES的环境搭建自然是十分简单,且本身就适应于分布式环境,因此这块就不多赘述.而其本身特性和查询语句这篇博文不会介绍,如果有机会会深入介绍. ​ 所 ...

  7. 20191127 Spring Boot官方文档学习(4.11)

    4.11.使用NoSQL技术 Spring Data提供了其他项目来帮助您访问各种NoSQL技术,包括: Redis MongoDB Neo4J Solr Elasticsearch Cassandr ...

  8. 3.3_springBoot2.1.x检索之RestHighLevelClient方式

    1.版本依赖 注意对 transport client不了解先阅读官方文档: transport client(传送门) 这里需要版本匹配,如失败查看官网或百度. pom.xml <?xml v ...

  9. Spring Boot 教程 - Elasticsearch

    1. Elasticsearch简介 Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearc ...

随机推荐

  1. Jenkins集成jacoco收集单元测试覆盖率

    Jenkins集成jacoco收集单元测试覆盖率 2020-02-28 目录 0 整体思路1 Jenkins创建JacocoIntegrateTestDemo项目2 配置源码管理3 配置Build4 ...

  2. 记一个开发是遇到的坑之Oralce 字符串排序

    简单描述一下情况,就是存储过程中用一个字符串类型的字段作为患者就诊的排序号,结果莫名发现叫完1号后叫了11.12等患者.用户的反馈不一定准确,自己加了日志的,赶紧拷贝日志来观察一下.结果发现实际情况就 ...

  3. opencv —— getRotationMatrix2D、warpAffine 仿射变换实现图像旋转缩放

    仿射变换的基本概念 仿射变换是一种二维坐标(x, y)到二维坐标(u, v)的线性变换,其数学表达式形式如下: 对应的齐次坐标矩阵表示形式为: 仿射变换保持了二维图形的“平直性”(直线经仿射变换后依然 ...

  4. R语言入门:使用RStudio的基本操作

    R语言在人工智能,统计学,机器学习,量化投资,以及生物信息学方面有着十分广泛的运用.也是我大学的必修课,因此这里梳理一些有关R语言的知识点,做做记录. 首先我们需要知道R语言的工作区域,R语言默认的工 ...

  5. Umi 小白纪实(一)—— 创建项目&常用配置

    umi 是一个企业级 react 应用框架,也是蚂蚁金服的底层前端框架 <蚂蚁金服的前端框架和工程化实践> 一.安装脚手架 在创建项目之前,需要保证有 node 8.10 以上的环境 可以 ...

  6. Android实战项目——家庭记账本(三)

    今天完成的主要内容有: 1.主页面账单明细部分细节展示 2.对每个列表项,点击打开新的可编辑修改具体页面 3.实现了搜索页面的UI布局 4.优化了部分页面的UI,提升用户视觉和使用体验 实现效果如下: ...

  7. EasyUI笔记(五)表单

    本系列只列出一些常用的属性.事件或方法,具体完整知识请查看API文档 Form(表单) 创建一个简单的HTML表单.构建一个包含id.action和method值的表单元素. <form id= ...

  8. 8组 上课啦(Class BUddy Pro)使用体验

    下载上课啦app 进入页面显示的是一个第1周的课表,和可以看到本周为第几周,点击周可以调整第几周显示课表 ,课表内容为整周内容,本周内容一目了然.点击右上角可以进入主设置页面,设置页面可以设置静音模式 ...

  9. P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]

    Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...

  10. 关于Dijk采访的一些感想

    有效的程序员不应该浪费很多时间用于程序调试,他们应该一开始就不要把故障引入! 反复,一遍又一遍的尝试,真的会让人心烦,对于有的问题解决不了,其实有很多原因,写出来的程序其实是非常考验人的细节处理能力的 ...