ElasticSearch Java High level Rest Client 官方文档中文翻译 一
纯粹记录自己在看官网的es rest high level api 时的翻译笔记,可以对照着官网文档看。
为什么不用 spring data es ?
1. rest high level api 支持异步操作,提交请求之后直接返回
2. 更接近原生的es http请求方式
- ElasticSearch Java High level Rest Client 官方文档中文翻译 一
一、 Getting start
1.1 maven依赖:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.7.0</version>
</dependency>
1.2 初始化
RestHighLevelClient实例需要一个Rest低级别的客户端生成器来构建
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
高级客户端将在内部基于提供的构建器创建用于执行请求的低级客户端,该低级客户端维护一个连接池并启动一些线程,因此你在完全正确的使用它之后关闭高级客户端,这反过来又将关闭内部低级客户端以释放连接资源.
client.close();
1.3 RequestOptions 请求参数
所有的RestHighLevelClient都可以使用RequestOptions来定义你的所有请求,并且其不会改变Elasticsearch执行请求的方式。
例如,在这里您可以指定一个位置 NodeSelector来控制哪个节点接收请求。有关自定义选项的更多示例,请参见低级客户端文档。
private static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
builder.addHeader("Authorization", "Bearer " + TOKEN);
builder.setHttpAsyncResponseConsumerFactory(
new HttpAsyncResponseConsumerFactory
.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
1.4 Asynchronous usage 异步使用rest high level client
跨不同客户端的所有方法都以传统的同步和异步变体形式存在。区别在于异步请求在REST Low Level Client中使用异步请求。如果您正在执行多个请求,或者正在使用rx java,Kotlin协同例程或类似框架,则此功能很有用。
可以通过以下事实来识别异步方法:它们的名称中带有单词“ Async”并返回一个Cancellable实例。异步方法接受与同步变量相同的请求对象,并接受泛型ActionListenerwhere T是同步方法的返回类型。
所有异步方法都返回一个Cancellable对象,该对象带有cancel您可能要中止请求时可以调用的方法。取消不再需要的请求是避免对Elasticsearch施加不必要负载的好方法。
使用Cancellable实例是可选的,如果不需要,可以放心地忽略它。一个用例是将其与例如Kotlin’s一起使用suspendCancellableCoRoutine。
二 、 Document APIS 文档操作API
2.1 Index API 索引API
一个索引请求需要一下几个组成部分
- index 索引
- Document id for the request 文档id
- Document source provided as a String 文档内容
IndexRequest request = new IndexRequest("posts");
request.id("1");
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
其中文档可以有以下几种形式
Document source provided as a Map which gets automatically converted to JSON format
以map相识提供文档数据,自动转变为Json形式
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("user", "kimchy");
jsonMap.put("postDate", new Date());
jsonMap.put("message", "trying out Elasticsearch");
IndexRequest indexRequest = new IndexRequest("posts")
.id("1").source(jsonMap);
- Document source provided as an XContentBuilder object, the Elasticsearch built-in helpers to generate JSON content 以XContentBuilder对象形式。
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("user", "kimchy");
builder.timeField("postDate", new Date());
builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("posts")
.id("1").source(builder);
- 以Obejct对象的key -value 形式
Document source provided as Object key-pairs, which gets converted to JSON format
IndexRequest indexRequest = new IndexRequest("posts")
.id("1")
.source("user", "kimchy",
"postDate", new Date(),
"message", "trying out Elasticsearch");
Optional arguments 可选参数 :
- Routing value
request.routing("routing");
- Timeout to wait for primary shard to become available as a TimeValue 等待主分片的可用时间
- Timeout to wait for primary shard to become available as a String 以字符串形式的等待主分片的可用时间
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
- Refresh policy as a WriteRequest.RefreshPolicy instance
刷新策略 - Refresh policy as a String
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
request.setRefreshPolicy("wait_for");
- version 版本
request.version(2);
- Version type 版本类型
request.versionType(VersionType.EXTERNAL);
- Operation type provided as an DocWriteRequest.OpType value
- Operation type provided as a String: can be create or index (default)
request.opType(DocWriteRequest.OpType.CREATE);
request.opType("create");
- The name of the ingest pipeline to be executed before indexing the document
在索引文档之前要执行的pipeline 名称
request.setPipeline("pipeline");
同步执行
当以如下方式执行Index请求的时候,客户端必须等收到回复才能继续执行下去。
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
同步操作可能会抛出一个IOException,因为有可能出现了解析 rest resonse错误,请求超时,或者服务端没有返回回复的错误。
在服务器返回4xx或5xx错误代码的情况下,high-level clien尝试改为解析响应正文错误详细信息,然后抛出ElasticsearchException并将原始的ResponseException作为抑制的异常添加到它。
异步执行
执行一个IndexRequest也可以使用异步的形式,这样客户端就可以直接返回,无需等待,用户需要通过将请求和侦听器传递给异步索引方法来指定如何处理响应或潜在的失败。
client.indexAsync(request, RequestOptions.DEFAULT, listener);
可以通过listener获取异步请求执行的结果。
异步方法不会阻塞并且立马就返回了,一旦请求执行成功,就会执行ActionListener的onResponse方法,一旦执行完毕就会执行onFailure方法。故障情况和预期的异常与同步执行情况相同。
典型的listenerindex如下所示:
- onResponse 请求执行成功的时候调用
- onFailure 失败的时候调用
listener = new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
Index Response 响应
可以通过indexResponse来获取请求执行过程的一些信息
- 文档首次创建
- 文档更新
- 执行成功的切片数小于总的切片数
- 潜在的错误
String index = indexResponse.getIndex();
String id = indexResponse.getId();
if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
}
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
}
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure :
shardInfo.getFailures()) {
String reason = failure.reason();
}
}
If there is a version conflict, an ElasticsearchException will be thrown: 如果出现了文档冲突,就会抛出ElasticsearchException
IndexRequest request = new IndexRequest("posts")
.id("1")
.source("field", "value")
.setIfSeqNo(10L)
.setIfPrimaryTerm(20);
try {
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
} catch(ElasticsearchException e) {
if (e.status() == RestStatus.CONFLICT) {
}
}
Same will happen in case opType was set to create and a document with same index and id already existed: 如果创建的id 与文档中存在id 出现重复也会抛出ElasticsearchException
IndexRequest request = new IndexRequest("posts")
.id("1")
.source("field", "value")
.opType(DocWriteRequest.OpType.CREATE);
try {
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
} catch(ElasticsearchException e) {
if (e.status() == RestStatus.CONFLICT) {
}
}
2.2 Get API Get请求API
Get Request
get请求需要一下几个参数
- 索引名
- 文档id
GetRequest getRequest = new GetRequest(
"posts",
"1");
可选参数
- Disable source retrieval, enabled by default 禁用源检索,默认情况下启用
request.fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE);
- Configure source inclusion for specific fields 只查询source中的几个fields
String[] includes = new String[]{"message", "*Date"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext =
new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
-
Configure source exclusion for specific fields 排除source中的几个fields
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"message"};
FetchSourceContext fetchSourceContext =
new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
-
Configure retrieval for specific stored fields (requires fields to be stored separately in the mappings)
配置特定存储字段的检索(要求将字段分别存储在映射中) -
Configure retrieval for specific stored fields (requires fields to be stored separately in the mappings)
检索message存储的字段(要求将字段单独存储在映射中)
request.storedFields("message");
GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
String message = getResponse.getField("message").getValue();
- Routing value
request.routing("routing");
- Preference value
request.preference("preference");
- Set realtime flag to false (true by default)
request.realtime(false);
- Perform a refresh before retrieving the document (false by default)
request.refresh(true);
- Version
request.version(2);
- Version type
request.routing("routing");
Synchronous execution 同步执行
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
Asynchronous execution 异步执行
client.getAsync(request, RequestOptions.DEFAULT, listener);
ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse getResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
Get response get请求响应
返回的内容GetResponse允许检索请求的文档及其元数据和最终存储的字段。
- 以String形式获取文档
- 以Map<String, Object>形式获取文档
- 以byte[]形式获取文档
String index = getResponse.getIndex();
String id = getResponse.getId();
if (getResponse.isExists()) {
long version = getResponse.getVersion();
String sourceAsString = getResponse.getSourceAsString();
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
byte[] sourceAsBytes = getResponse.getSourceAsBytes();
} else {
}
-
如果文档不存在,即使返回404,getresponse也不会抛出异常,但是调用getresponse的isExists方法会返回false
-
如果get请求了一个不存在的index,会返回404状态码,抛出ElasticsearchException
GetRequest request = new GetRequest("does_not_exist", "1");
try {
GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
} catch (ElasticsearchException e) {
if (e.status() == RestStatus.NOT_FOUND) {
}
}
- 如果请求的版本号对不上的时候,就出现了版本冲突,同样也会抛出ElasticsearchException
try {
GetRequest request = new GetRequest("posts", "1").version(2);
GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.CONFLICT) {
}
}
2.3 Get source API 获取文档内容api
GetSourceRequest
一个GetSourceRequest需要以下几个参数
- 索引
- 文档id
GetSourceRequest getSourceRequest = new GetSourceRequest(
"posts",
"1");
可选参数
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"postDate"};
getSourceRequest.fetchSourceContext(
new FetchSourceContext(true, includes, excludes));
- FetchSourceContext的第一个参数fetchSource必须为true,否则就会抛出ElasticsearchException
- includes 和 excludes 也是可选参数
… 其余和之前的API类似
get source response
get source response 会返回一个Map<Stirng,Object> 形式的response
Map<String, Object> source = response.getSource();
2.4 Exists API 判断文档是否存在的API
如果文档存在Exists API 返回true,不存在则返回false
Exists Request
Exists API 和Get API一样使用GetRequest,支持其所有的可选参数,因为exists 只返回true 和 false , 建议可以关闭fetching _source 以及一些 stored fields 这样就可以执行一个轻量级的请求了
GetRequest getRequest = new GetRequest(
"posts",
"1");
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
Source Exists request
2.5 Delete API 删除文档api
Delete Request
DeleteRequest request = new DeleteRequest(
"posts",
"1");
删除文档API和之前的API的类似,响应API会有些不同
Delete Response
- 如果请求成功的切片数小于总的切片数
- 处理可能的错误
String index = deleteResponse.getIndex();
String id = deleteResponse.getId();
long version = deleteResponse.getVersion();
ReplicationResponse.ShardInfo shardInfo = deleteResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
//1.
}
//2.
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure :
shardInfo.getFailures()) {
String reason = failure.reason();
}
}
- 如果要删除的文档不存在
DeleteRequest request = new DeleteRequest("posts", "does_not_exist");
DeleteResponse deleteResponse = client.delete(
request, RequestOptions.DEFAULT);
if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
}
- 出现了版本冲突
try {
DeleteResponse deleteResponse = client.delete(
new DeleteRequest("posts", "1").setIfSeqNo(100).setIfPrimaryTerm(2),
RequestOptions.DEFAULT);
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.CONFLICT) {
}
}
2.6 Update API 更新文档api
UpdateRequest
UpdateRequest request = new UpdateRequest(
"posts",
"1");
Update API允许通过使用脚本或传递部分文档来更新现有文档。
Updates with a script 使用脚本更新
- Script parameters provided as a Map of objects 以map方式提供脚本参数
- Create an inline script using the painless language and the previous parameters
-
Sets the script to the update request 在update request 请求中设置脚本
Script stored = new Script(
ScriptType.STORED, null, "increment-field", parameters);
request.script(stored);
Update with a partial document 部分更新文档
只更新文档的一部分
- Partial document source provided as a String in JSON format 以json格式字符串提供文档的一部分
UpdateRequest request = new UpdateRequest("posts", "1");
String jsonString = "{" +
"\"updated\":\"2017-01-01\"," +
"\"reason\":\"daily update\"" +
"}";
request.doc(jsonString, XContentType.JSON);
- Partial document source provided as a Map which gets automatically converted to JSON format
通过XContentFactory.jsonBuilder构造Json字符串
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.timeField("updated", new Date());
builder.field("reason", "daily update");
}
builder.endObject();
UpdateRequest request = new UpdateRequest("posts", "1")
.doc(builder);
- Partial document source provided as Object key-pairs, which gets converted to JSON format 以Object key-pairs形式
UpdateRequest request = new UpdateRequest("posts", "1")
.doc("updated", new Date(),
"reason", "daily update");
Upsert
如果文档尚不存在,则可以使用以下upsert方法定义一些内容,这些内容将作为新文档插入:
String jsonString = "{\"created\":\"2017-01-01\"}";
request.upsert(jsonString, XContentType.JSON);
类似于局部文档更新时,内容upsert文件可以使用接受的方法定义String,Map,XContentBuilder或 Object密钥对。
optinonal arguments
- 设置更新失败的重试次数,有点类似于CAS
request.retryOnConflict(3);
Update Response
- 文档创建
- 文档更新
- 文档删除
- 文档和更新之前没区别
String index = updateResponse.getIndex();
String id = updateResponse.getId();
long version = updateResponse.getVersion();
if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
} else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
} else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) {
} else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) {
}