Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,本教程从Java语言角度讲解如何操作Elasticsearch,如果不熟悉Elasticsearch,可以先学习 Elasticsearch教程,掌握基本概念和查询语法。
教程基于ES官方的Java REST Client 进行讲解,老的Java API, ES 7.0.0以后将会废弃,不推荐继续使用。
兼容性说明
支持Elasticsearch 5.6.x 以上。
Java版本,最低要求是1.8
Maven配置
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.1</version>
</dependency>
你可以根据自己的ES版本选择对应的Java REST Client版本。
创建客户端
在操作ES之前需要创建一个client, ES请求都是通过client发送,通过client可以配置ES的服务地址、安全验证相关参数。
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
通常全局创建一个client即可,client内部维护了连接池,因此在不使用client的时候需要通过下面方式释放资源。
client.close();
创建索引
// 创建Request对象, 准备创建的索引名为twitter
CreateIndexRequest request = new CreateIndexRequest("twitter");
// 设置Request参数
request.settings(Settings.builder()
.put("index.number_of_shards", 3) // 设置分区数
.put("index.number_of_replicas", 2) // 设置副本数
);
// 通过JSON字符串的方式,设置ES索引结构的mapping
// ps: 通常都是通过json配置文件加载索引mapping配置,不需要拼接字符串。
request.mapping(
"{\n" +
" \"properties\": {\n" +
" \"message\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
"}",
XContentType.JSON);
// 执行请求,创建索引
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
if (createIndexResponse.isAcknowledged()) {
// 创建成功
}
插入数据
// 创建对应的Request请求,设置索引名为posts
IndexRequest request = new IndexRequest("posts");
// 设置文档id=1
request.id("1");
// 以json字符串的形式设置文档内容,也就是准备插入到ES中的数据
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
// 执行请求
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
查询数据
根据id查询一条数据
// 创建对应的Request对象,设置索引名为posts, 文档id=1
GetRequest getRequest = new GetRequest(
"posts",
"1");
// 执行ES请求
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
// 处理查询结果
String index = getResponse.getIndex();
String id = getResponse.getId();
// 检查文档是否存在
if (getResponse.isExists()) {
long version = getResponse.getVersion();
// 获取文档数据的json字符串形式,可以使用json库转换成Java对象
String sourceAsString = getResponse.getSourceAsString();
// 获取文档数据的Map形式
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
// 获取文档数据的字节数组形式
byte[] sourceAsBytes = getResponse.getSourceAsBytes();
} else {
// 文档不存在
}
更新数据
// 创建对应的Request对象,设置索引名为posts, 文档id=1
UpdateRequest request = new UpdateRequest("posts", "1");
// 以map形式,设置需要更新的文档字段
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("updated", new Date());
jsonMap.put("reason", "daily update");
request.doc(jsonMap);
// 执行请求
UpdateResponse updateResponse = client.update(
request, RequestOptions.DEFAULT);
删除数据
// 创建对应的Request对象,设置索引名为posts, 文档id=1
DeleteRequest request = new DeleteRequest(
"posts",
"1");
// 执行请求
DeleteResponse deleteResponse = client.delete(
request, RequestOptions.DEFAULT);
提示:详情,请参考后续章节。
本节主要讲解Java Elasticsearch RestHighLevelClient的配置详解。
RestHighLevelClient常用配置如下:
-
elasticsearch连接地址
-
elasticsearch账号/密码
-
Http请求头
-
连接超时
-
设置线程池大小
创建client
RestHighLevelClient 依赖 REST low-level client builder 进行配置,即依赖底层的RestClientBuilder对象进行参数设置
// 首先创建RestClientBuilder,后续章节通过RestClientBuilder对象进行参数配置。
RestClientBuilder restClientBuilder = RestClient.builder(
new HttpHost("localhost", 9200, "http"), // 设置ES服务地址,支持多个
new HttpHost("localhost", 9201, "http"));
// 创建RestHighLevelClient,•请求都是通过RestHighLevelClient实例发出去的。
RestHighLevelClient client = new RestHighLevelClient(restClientBuilder);
配置ES账号密码
restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
// 通过CredentialsProvider实例,配置账号和密码
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("user", "password"));
// 设置安全验证凭证
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
设置Http Header
// 创建header数组,可以设置多个header
Header[] defaultHeaders = new Header[]{new BasicHeader("header", "value")};
// 设置http header
restClientBuilder.setDefaultHeaders(defaultHeaders);
Timeout设置
配置Elasticsearch连接超时时间
restClientBuilder.setRequestConfigCallback(
new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(
RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder
.setConnectTimeout(5000) // 设置连接超时时间,5秒
.setSocketTimeout(60000); // 设置请求超时时间,1分种
}
});
设置线程池大小
restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(
HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultIOReactorConfig(
IOReactorConfig.custom()
.setIoThreadCount(10) // 设置线程数
.build());
}
});
Document APIs
Java Elasticsearch Index Api
Java Elasticsearch Index API 主要用于插入或者更新文档数据。
创建Index Request
// 创建Index Request,设置索引名为: posts
IndexRequest request = new IndexRequest("posts");
// 设置文档ID
request.id("1");
设置文档内容
支持以JSON字符串形式或者map形式设置文档内容。
Json字符串形式:
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
Map形式:
// 创建map
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("user", "kimchy");
jsonMap.put("postDate", new Date());
jsonMap.put("message", "trying out Elasticsearch");
// 设置文档内容
request.source(jsonMap);
其他可选参数
routing
设置路由字段
request.routing("routing");
timeout
设置单个请求超时参数
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
Version
设置文档版本
request.version(2);
操作类型
Index api支持两类操作:create 或者 index (默认)
request.opType("create");
执行请求
以同步的方式执行ES请求
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
以异步的方式执行请求
client.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
// 请求成功回调函数
}
@Override
public void onFailure(Exception e) {
// 请求失败回调函数
}
});
处理请求结果
// 获取索引名
String index = indexResponse.getIndex();
// 获取文档ID
String id = indexResponse.getId();
if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
// 成功创建文档
} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
// 成功更新文档
}
Java Elasticsearch Get Api
Get Api 主要用于根据文档ID查询索引数据。
创建Get Request
// 创建GetRequest,索引名=posts, 文档ID=1
GetRequest getRequest = new GetRequest(
"posts",
"1");
其他可选参数
是否返回文档内容
默认返回文档内容
// 不返回文档内容
request.fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE);
返回指定字段
// 设置返回指定字段
String[] includes = new String[]{"message", "*Date"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext =
new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
过滤指定字段
String[] includes = Strings.EMPTY_ARRAY;
// 过滤指定字段
String[] excludes = new String[]{"message"};
FetchSourceContext fetchSourceContext =
new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);