ElasticSearch(6)------Java应用操作ElasticSearch
前言
在前面的博文中,我们在Kibana中对ElasticSearch中的文档数据进行了各种查询和添加,下面我们来看看怎么在java中连接ElasticSearch操作文档
正文
1. 创建java工程
首先,我们创建一个maven工程,在这里我们使用IDEA来开发,在pom文件中引入ElasticSearch的客户端插件:
<!--引入elasticsearch客户端-->
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/transport -->
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.7.1</version>
</dependency>
<!--引入junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
在这里引入的org.elasticsearch.client
是ElasticSearch官方提供的在java中连接ES的jar包,我们可以直接使用,比较方便.
2. 创建ElasticSearch客户端
根据我们的开发经验,要连接ES,就需要一个客户端,在这里,连接ES的客户端你需要知道ES集群的名字以及IP地址,因为在实际的生产环境下,ES一般是集群部署的,要查看ES集群的名字,你可以在ES文件夹下的config中找到ElasticSearch.yml文件,在这个文件中你就可以自己指定或者使用默认的名字,我们查看elasticsearch.yml,可以看到cluster.name
的值是docker-cluster
,因为我这里是用docker运行的ElasticSearch.下面是获取ES客户端的方法,我们可以提取成一个单独的放来调用.
/**
* 获取ElasticSearch客户端
* @return
* @throws UnknownHostException
*/
private TransportClient getTransportClient() throws UnknownHostException {
//首先指定ES集群
Settings settings = Settings.builder().put("cluster.name", "docker-cluster").build();
//创建客户端
return new PreBuiltTransportClient(settings)
.addTransportAddress(new TransportAddress(InetAddress.getByName("192.168.137.47"),9300));
}
在后面的查询或者添加中,我们就可以使用这里的TransportClient
来操作elasticsearch
3. 使用client操作es
查询文档
下面我们来使用上面获取的ES客户端查询一下ElasticSearch:
/**
* 查询文档
* @throws UnknownHostException
*/
@Test
public void test1() throws UnknownHostException {
TransportClient client = getTransportClient();
//查询数据
GetResponse response = client.prepareGet("index3", "user", "2").execute().actionGet();
System.out.println(response);
client.close();
}
在查询的时候,我们需要指定一个index、type和id来进行精确的查找,查找出来的内容被封装在GetResponse对象中,切莫忘记在查询完成后关闭连接.
添加文档
在使用java对ES添加文档的时候,我们需要创建一个文档对象,然后操作客户端对文档进行上床,在这里,我们的文档对象是XContentBuilder
,代码如下:
/**
* 添加文档
*/
@Test
public void test2() throws Exception {
TransportClient client = getTransportClient();
//创建文档对象
XContentBuilder docment = XContentFactory.jsonBuilder().startObject()
.field("name", "剑小纯")
.field("gender", true)
.field("age", 88).endObject();
//添加文档
IndexResponse response = client.prepareIndex("index3", "user", "47").setSource(docment).get();
System.out.println(response);
client.close();
}
更新文档
更新文档有两种情况:
-
若要更新的文档存在,则更新,否则不作处理,即update
@Test public void testUpdate() throws Exception{ //获取客户端 TransportClient client = getTransportClient(); //创建更新的内容 UpdateRequest updateRequest = new UpdateRequest(); updateRequest.index("index3").type("user").id("47") .doc( XContentFactory.jsonBuilder().startObject() .field("name", "李忘生").endObject() ); //执行更新操作 UpdateResponse updateResponse = client.update(updateRequest).get(); System.out.println(updateResponse); //以下方法也可以实现更新 /*UpdateResponse response = client.prepareUpdate("index3", "user", "47") .setDoc(XContentFactory.jsonBuilder().startObject() .field("name", "曹雪阳").endObject() ).get(); System.out.println(response);*/ }
可以看到,在更新的时候是可以有多重方法可以选择,具体使用哪种方法来操作根据自己的习惯即可.
-
若更新的文档存在则更新,若不存在则添加,即upsert
@Test public void testUpdasert() throws Exception{ TransportClient client = getTransportClient(); //构造要添加的文档,在更新失败的时候添加该文档 XContentBuilder builder = XContentFactory.jsonBuilder().startObject() .field("name", "李复") .field("gender", false) .field("age", 20).endObject(); IndexRequest addRequest = new IndexRequest("index3", "user", "48") .source(builder); //创建更新请求体 UpdateRequest request = new UpdateRequest("index3", "user", "48") .doc(XContentFactory.jsonBuilder().startObject() .field("name", "赵大宝").endObject() ).upsert(builder); UpdateResponse response = client.update(request).get(); System.out.println(response); client.close(); }
在upsert中,需要指定两种情况下的不同文档内容.
删除文档
删除文档比较简单,我们只需要指定对应的id即可
@Test
public void test3() throws Exception {
TransportClient client = getTransportClient();
//根据id删除文档
DeleteResponse response = client.prepareDelete("index3", "user", "47").get();
System.out.println(response);
client.close();
}
批量查询
我们也可以批量查询文档:
@Test
public void testMget() throws Exception{
TransportClient client = getTransportClient();
MultiGetResponse responses = client.prepareMultiGet()
.add("index3", "user", "47")
.add("index1", "books", "2").get();
for (MultiGetItemResponse respons : responses) {
System.out.println(respons.getResponse());
}
client.close();
}
批量增加文档
可以一次增加多个文档到索引中:
@Test
public void testBulk() throws Exception{
//获取客户端
TransportClient client = getTransportClient();
BulkRequestBuilder requestBuilder = client.prepareBulk();
//批量添加
requestBuilder.add(client.prepareIndex("index1","books","100")
.setSource(XContentFactory.jsonBuilder().startObject()
.field("name","曹炎烈1")
.field("gender","ture")
.field("age",10).endObject()));
requestBuilder.add(client.prepareIndex("index1","books","101")
.setSource(XContentFactory.jsonBuilder().startObject()
.field("name","西游记1")
.field("price","25.25")
.field("createtimes","1111-01-01")
.endObject()));
BulkResponse bulkItemResponses = requestBuilder.get();
System.out.println(bulkItemResponses.status());
client.close();
}
查询所有文档
可以直接查询某个索引下的所有文档:
/**
* 查询所有match_all
*/
@Test
public void testMatchall() throws Exception{
TransportClient client = getTransportClient();
QueryBuilder qb = QueryBuilders.matchAllQuery();
SearchResponse resp = client.prepareSearch("index3").setQuery(qb).get();
System.out.println(resp);//数据在resp的hits中
client.close();
}
除了以上的查询,还有其他的聚合查询,分组统计等操作,具体的姿势可以直接在官方文档get到,这里就不做赘述.
总结
总体来说,在java中操作es还是比较简单的,当初,除了基本的CRUD操作,我们也可以使用java来监控es集群的健康状况,使用情况等,但是在Kibana如此方便的情况下,使用java来自己写代码就显得比较繁琐了.