纯粹记录自己在看官网的es rest high level api 时的翻译笔记,可以对照着官网文档看。
Java High level Rest Client
为什么不用 spring data es ?
1. rest high level api 支持异步操作,提交请求之后直接返回
2. 更接近原生的es http请求方式
org.elasticsearch.client
elasticsearch-rest-high-level-client
7.7.0
RestHighLevelClient实例需要一个Rest低级别的客户端生成器来构建
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
高级客户端将在内部基于提供的构建器创建用于执行请求的低级客户端,该低级客户端维护一个连接池并启动一些线程,因此你在完全正确的使用它之后关闭高级客户端,这反过来又将关闭内部低级客户端以释放连接资源.
client.close();
所有的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();
}
跨不同客户端的所有方法都以传统的同步和异步变体形式存在。区别在于异步请求在REST Low Level Client中使用异步请求。如果您正在执行多个请求,或者正在使用rx java,Kotlin协同例程或类似框架,则此功能很有用。
可以通过以下事实来识别异步方法:它们的名称中带有单词“ Async”并返回一个Cancellable实例。异步方法接受与同步变量相同的请求对象,并接受泛型ActionListenerwhere T是同步方法的返回类型。
所有异步方法都返回一个Cancellable对象,该对象带有cancel您可能要中止请求时可以调用的方法。取消不再需要的请求是避免对Elasticsearch施加不必要负载的好方法。
使用Cancellable实例是可选的,如果不需要,可以放心地忽略它。一个用例是将其与例如Kotlin’s一起使用suspendCancellableCoRoutine。
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 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);
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);
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");
request.routing("routing");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
request.setRefreshPolicy("wait_for");
request.version(2);
request.versionType(VersionType.EXTERNAL);
request.opType(DocWriteRequest.OpType.CREATE);
request.opType("create");
在索引文档之前要执行的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如下所示:
listener = new ActionListener() {
@Override
public void onResponse(IndexResponse indexResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
可以通过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) {
}
}
get请求需要一下几个参数
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);
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();
request.routing("routing");
request.preference("preference");
request.realtime(false);
request.refresh(true);
request.version(2);
request.routing("routing");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
client.getAsync(request, RequestOptions.DEFAULT, listener);
ActionListener listener = new ActionListener() {
@Override
public void onResponse(GetResponse getResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
返回的内容GetResponse允许检索请求的文档及其元数据和最终存储的字段。
String index = getResponse.getIndex();
String id = getResponse.getId();
if (getResponse.isExists()) {
long version = getResponse.getVersion();
String sourceAsString = getResponse.getSourceAsString();
Map 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) {
}
}
try {
GetRequest request = new GetRequest("posts", "1").version(2);
GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.CONFLICT) {
}
}
一个GetSourceRequest需要以下几个参数
GetSourceRequest getSourceRequest = new GetSourceRequest(
"posts",
"1");
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"postDate"};
getSourceRequest.fetchSourceContext(
new FetchSourceContext(true, includes, excludes));
… 其余和之前的API类似
get source response 会返回一个Map
Map source = response.getSource();
如果文档存在Exists API 返回true,不存在则返回false
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_");
DeleteRequest request = new DeleteRequest(
"posts",
"1");
删除文档API和之前的API的类似,响应API会有些不同
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) {
}
}
UpdateRequest request = new UpdateRequest(
"posts",
"1");
Update API允许通过使用脚本或传递部分文档来更新现有文档。
Sets the script to the update request 在update request 请求中设置脚本
Script stored = new Script(
ScriptType.STORED, null, "increment-field", parameters);
request.script(stored);
只更新文档的一部分
UpdateRequest request = new UpdateRequest("posts", "1");
String jsonString = "{" +
"\"updated\":\"2017-01-01\"," +
"\"reason\":\"daily update\"" +
"}";
request.doc(jsonString, XContentType.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);
UpdateRequest request = new UpdateRequest("posts", "1")
.doc("updated", new Date(),
"reason", "daily update");
如果文档尚不存在,则可以使用以下upsert方法定义一些内容,这些内容将作为新文档插入:
String jsonString = "{\"created\":\"2017-01-01\"}";
request.upsert(jsonString, XContentType.JSON);
类似于局部文档更新时,内容upsert文件可以使用接受的方法定义String,Map,XContentBuilder或 Object密钥对。
request.retryOnConflict(3);
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) {
}