从Elasticsearch 5.0开始引入了REST Client,使用HTTP的协议操作ES服务器。ES原生的Transport Client将在8.0后彻底取消,因此官方推荐使用REST API. 这是因为REST Client的初始化构建的线程的安全的,与应用的生命周期相同,但是使用完客户端后要关闭客户端来释放资源。
Elasticsearch Java REST API分为低级(low-level)和高级(high-level)两个接口,其中:
- Java Low Level REST Client 允许用HTTP协议与ES集群通信,是面向用户的。
- Java high Level REST Client 基于低级客户端,面向开发者,开发者可以用管饭提供的各种API实现自己的功能
官方的文档在:
Java REST Clientwww.elastic.co这部分介绍低级客户端
五、Java Low Level REST API
低级客户端的特效包括:
- 最小化依赖
- 所有节点(nodes)的负载均衡
- 某个节点发生故障会自动转移到其他节点
- 对于失败的链接给予乘法,也就是失败次数越多,client下次尝试重新链接的时间就越长,
- 持续练级
- 跟踪(tracing)请求和相应的记录
- 可以自动发现集群中的节点(cluster nodes)
5.1 添加依赖
可以在maven的pom.xml中添加如下依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.3.2</version>
</dependency>
对于gradle工程,则添加:
dependencies {
compile 'org.elasticsearch.client:elasticsearch-rest-client:6.3.2'
}
不同版本的ES选择对应的REST 客户端
5.2 初始化
使用ES 官方提供的REST接口时需要先初始化,使用ResClientBuilder类初始化,如下:
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")).build();
调用完之后一定要关闭客户端
restClient.close();
5.3 请求
REST Client初始化后,可用同步方法performRequest()或者异步方法performRequestAsync()方法完成请求。
查看索引中节点的信息,可以直接用GET方法得到
Response response = restClient.performRequest("GET", "/");
查询某个属性和某个值为true的文档
Map<String, String> params = Collections.singletonMap("属性", "值");
Response response = restClient.performRequest("GET", "/", params);
如查看索引中”pretty“属性为true的文档,
Map<String, String> params = Collections.singletonMap("pretty", "true");
Response response = restClient.performRequest("GET", "/", params);
此外,可以用Java中的HashMap自定义JSON请求
Map<String, String> params = Collections.emptyMap();
String jsonString = "JSON请求的字符串";
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
Response response = restClient.performRequest("PUT", "索引/类型/id", params, entity);
如自定义一个类型为doc的文档,属于索引posts,文档id为1,该文档描述了用户名(user),提交时间(postDate)和信息(message)三个属性,用HashMap建立的JSON请求,并把该文档添加到索引中的代码为:
Map<String, String> params = Collections.emptyMap();
String jsonString = "{" +
""user":"kimchy"," +
""postDate":"2013-01-30"," +
""message":"trying out Elasticsearch"" +
"}";
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
Response response = restClient.performRequest("PUT", "/posts/doc/1", params, entity);
在比如,在自定义的spnews的索引中,查询关键字为周琦的有关文档
String key_word = "周琦";
String queryString = "{" +
" "query":{"+
" "match":{"+
" "key_word":""+key_word+"""+
" }" +
" }"+
" }";
HttpEntity entity = new NStringEntity(queryString,ContentType.APPLICATION_JSON);
String content = null;
try{
Response response = restClient.performRequest("GET","/spnews/_search", params, entity);
System.out.println(response.getStatusLines().getStatusCode());
String responseBody = null;
responseBody = EntityUtils.toString(response.getEntity());
}
此外还有异步请求,需要用listener监听。
六、Java High Level REST API
Java High Level Client 运行在Java Low Level REST 客户端上,面向开发人员,高级客户端提供API的具体方法,这些方法以请求对象(Request Object)为输入,返回响应对象(Response Object),每个API的方法都可以用同步或者异步的方式调用,异步方法返回的对象需要用监听器(listener)来接受。
Java High Level Client 依赖于ES核心工程(core project),因此与ES原生的Java API中的TransportClient有相同的输入和输出。由于8.0版本后,官方不在支持TransportClient,因此推荐把现有的用TransportClient写的代码移植到REST Client中,官方的移植的手册为
Migration Guidewww.elastic.co兼容性方法,High Level REST Client 与ES 版本号保持一致,并且可以在允许的最小版本(minor version)上运行。最推荐的还是让ES与REST Client的版本保持一致。
目前,Java REST Client API中已经实现了原生API中的大部分方法,开发者可以在官方的github issue上提交暂时还未实现的方法。当然这些方法都可以用JSON请求Low Level REST Client手动实现。
6.1 添加依赖
与Low Level REST Client一样,High Level REST Client也可以再maven中添加依赖实现:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.3.2</version>
</dependency>
gradle则是
dependencies {
compile 'org.elasticsearch.client:elasticsearch-rest-high-level-client:6.3.2'
}
6.2 初始化
High-level REST 客户端使用RestHighLevelClient类来创建客户端
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
使用完后,要关闭客户端
client.close();
6.3 对索引的操作
6.3.1 查看索引是否存在
使用GetIndexRequest来查看索引是否存在,如下
GetIndexRequest request = new GetIndexRequest();
request.indices("索引名");
对于建立的request对象,可是用一个bool变量来表示索引是否存在,6.3版本以前可以用:
boolean exists = client.indices().exists(request);
6.4版本开始使用
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
该请求也可以添加方法
request.local(false); //是否返回主节点信息
request.humanReadable(true); //是否返回可读的信息
request.includeDefaults(false); //是否返回每个结点的默认信息
request.indicesOptions(indicesOptions); //控制结点的其他配置
6.3.2 删除索引
使用GetIndexRequest删除索引
DeleteIndexRequest request = new DeleteIndexRequest("索引名");
6.3版本前使用DeleteIndexResponse执行删除
DeleteIndexResponse deleteIndexResponse = client.indices().delete(request);
6.4版本后使用
DeleteIndexResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT);
可以用一个boolean类型的变量判断是否删除成功
boolean acknowledged = deleteIndexResponse.isAcknowledged();
删除一个不存在的索引会抛出ElasticsearchException的异常,因此完整的删除操作为:
try {
DeleteIndexRequest request = new DeleteIndexRequest("does_not_exist");
client.indices().delete(request);
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
}
}
6.4版本以后则是:
try {
DeleteIndexRequest request = new DeleteIndexRequest("does_not_exist");
client.indices().delete(request, RequestOptions.DEFAULT);
} catch (ElasticsearchException exception) {
if (exception.status() == RestStatus.NOT_FOUND) {
}
}
6.3.3 创建索引
使用CreateIndexRequest创建请求类
CreateIndexRequest request = new CreateIndexRequest("索引名");
可以使用该类下的settings方法设置索引的一些属性,比如分片数,冗余数
request.settings(Settings.builder()
.put("index.number_of_shards", 3)
.put("index.number_of_replicas", 2)
);
上边介绍说,所有ES的请求都是JSON,因此可以用各种创建JSON的方式设置索引的属性,比如用纯文本创建。使用到的JSON请求,类型为_doc,具体属性为:
{
"_doc":
{
"properties":
{
"message":
{
"type": "text"
}
}
}
}
纯文本构建的JSON请求设置索引的属性的代码为:
request.mapping("_doc",
"{n" +
" "_doc": {n" +
" "properties": {n" +
" "message": {n" +
" "type": "text"n" +
" }n" +
" }n" +
" }n" +
"}",
XContentType.JSON);
比如用HashMap构建JSON请求:
Map<String, Object> jsonMap = new HashMap<>();
Map<String, Object> message = new HashMap<>();
message.put("属性1", "值1");
Map<String, Object> properties = new HashMap<>();
properties.put("属性2", message);
Map<String, Object> mapping = new HashMap<>();
mapping.put("属性3", properties);
jsonMap.put("类型名", mapping);
request.mapping("类型名", jsonMap);
上述例子就可以写成:
Map<String, Object> jsonMap = new HashMap<>();
Map<String, Object> message = new HashMap<>();
message.put("type", "text");
Map<String, Object> properties = new HashMap<>();
properties.put("message", message);
Map<String, Object> mapping = new HashMap<>();
mapping.put("properties", properties);
jsonMap.put("_doc", mapping);
request.mapping("_doc", jsonMap);
还可以使用ES内建的JSON helper生成JSON格式的请求,上边的例子可以写成
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.startObject("_doc");
{
builder.startObject("properties");
{
builder.startObject("message");
{
builder.field("type", "text");
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
request.mapping("_doc", builder);
还可以用键-值组合自动生成JSON格式的设置项
request.mapping("_doc", "message", "type=text");
对于创建好的索引,还可以起个别名
request.alias(new Alias("twitter_alias").filter(QueryBuilders.termQuery("user", "kimchy")));
也可直接使用未加任何处理的字符串构建JSON请求,并设置各种属性来创建索引
request.source("{n" +
" "settings" : {n" +
" "number_of_shards" : 1,n" +
" "number_of_replicas" : 0n" +
" },n" +
" "mappings" : {n" +
" "_doc" : {n" +
" "properties" : {n" +
" "message" : { "type" : "text" }n" +
" }n" +
" }n" +
" },n" +
" "aliases" : {n" +
" "twitter_alias" : {}n" +
" }n" +
"}", XContentType.JSON);
对于创建索引的请求,可是用CreateIndexRequest执行创建
CreateIndexResponse createIndexResponse = client.indices().create(request);
6.4版本以上使用
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
用以下语句表示创建成功
boolean acknowledged = createIndexResponse.isAcknowledged();
boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();
创建完的索引还需要设置映射,映射就相当于数据库中的字段,映射同样用JSON请求实现,如下
XContentBuilder mapjasonbuilder = mappingIndexJSON()
request.mapping("类型名",mapjasonbuilder)
其中mappingIndexJSON()是用XContentBuilder来创建JSON请求,与上边的创建设置项的JSON类似
6.4 对文档的操作
补充中...