19、ES实战:Java高级客户端文档管理

本学习笔记基于ElasticSearch 7.10版本,旧版本已经废弃的功能暂时不做笔记,以后有涉及到再做补充。

上一章我们学习了Java高级客户端中的索引部分,现在继续来学习文档管理。

同样,创建一个新的Maven工程,引入依赖。需要注意,依赖的版本和 Es 的版本要对应:

<dependencies>
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.10.0</version>
    </dependency>
</dependencies>

1、添加文档

public class DocTest1 {
   
     
    public static void main(String[] args) throws IOException {
   
     
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http"),
                new HttpHost("localhost", 9202, "http")
        ));
        // 1.构建一个 IndexRequest 请求,参数就是索引名称
        IndexRequest request = new IndexRequest("book");
        // 2.给请求配置一个 id,这个就是文档 id。如果指定了 id,相当于 put book/_doc/id ,也可以不指定 id,相当于 post book/_doc
        request.id("1");
        // 3.构建索引文本,有三种方式:JSON 字符串、Map 对象、XContentBuilder
        // 首先演示JSON
        request.source("{\"name\": \"三国演义\",\"author\": \"罗贯中\"}", XContentType.JSON);
        // 4.执行请求,同样有同步和异步两种方式
        // 同步
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        // 5.查看请求响应报文
        // 获取文档id
        String id = indexResponse.getId();
        System.out.println("id = " + id);
        // 获取索引名称
        String index = indexResponse.getIndex();
        System.out.println("index = " + index);
        // 判断文档是否添加成功
        if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
   
     
            System.out.println("文档添加成功");
        }
        // 判断文档是否更新成功(如果 id 已经存在)
        if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
   
     
            System.out.println("文档更新成功");
        }
        ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
        // 判断分片操作是否都成功
        if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
   
     
            System.out.println("有存在问题的分片");
        }
        // 有存在失败的分片
        if (shardInfo.getFailed() > 0) {
   
     
            for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
   
     
                System.out.println("failure.reason() = " + failure.reason());
            }
        }

        //异步
        /*client.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
            @Override
            public void onResponse(IndexResponse indexResponse) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        });*/
        client.close();
    }
}

上面这段代码,在添加文档的时候如果索引不存在,会同步创建索引。因为之前我们设置了创建索引默认的分片和副本都是1,就不会出现分片失败的情况。

为了演示分片失败的情况,我们就需要定义分片数 ≥ 集群数,集群数是3,所以分片数也设置为3:

PUT book
{
   
     
  "settings": {
   
     
    "number_of_replicas": 3,
    "number_of_shards": 3
  }
}

然后我们再来执行上面的代码,就会出现“有存在问题的分片”的情况了。

构建索引文本的另外两种方式:

// 3.构建索引文本,有三种方式:JSON 字符串、Map 对象、XContentBuilder
// 首先演示JSON
// request.source("{\"name\": \"三国演义\",\"author\": \"罗贯中\"}", XContentType.JSON);
//Map<String, String> map = new HashMap<>();
//map.put("name", "水浒传");
//map.put("author", "施耐庵");
//request.source(map).id("99");
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
jsonBuilder.startObject();
jsonBuilder.field("name", "西游记");
jsonBuilder.field("author", "吴承恩");
jsonBuilder.endObject();
request.source(jsonBuilder);

2、删除文档

public class DeleteDoc {
   
     
    public static void main(String[] args) throws IOException {
   
     
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http"),
                new HttpHost("localhost", 9202, "http")
        ));
        DeleteRequest request = new DeleteRequest("book", "99");
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        System.out.println("response.getId() = " + response.getId());
        System.out.println("response.getIndex() = " + response.getIndex());
        System.out.println("response.getVersion() = " + response.getVersion());
        ReplicationResponse.ShardInfo shardInfo = response.getShardInfo();
        if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
   
     
            System.out.println("有分片存在问题");
        }
        if (shardInfo.getFailed() > 0) {
   
     
            for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
   
     
                System.out.println("failure.reason() = " + failure.reason());
            }
        }
        client.close();
    }
}

删除文档的响应报文和添加文档响应报文类似。

3、获取文档

public class GetDoc {
   
     
    public static void main(String[] args) throws IOException {
   
     
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http"),
                new HttpHost("localhost", 9202, "http")
        ));
        GetRequest request = new GetRequest("book", "1");
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        String id = response.getId();
        String index = response.getIndex();
        System.out.println("response.getId() = " + id);
        System.out.println("response.getIndex() = " + index);
        if (response.isExists()) {
   
     
            long version = response.getVersion();
            System.out.println(version);
            String sourceAsString = response.getSourceAsString();
            System.out.println(sourceAsString);
        } else {
   
     
            System.out.println("文档不存在");
        }
        client.close();
    }
}

4、判断文档是否存在

判断文档是否存在和获取文档的 API 是类似。只不过在判断文档是否存在时,不需要获取 source。

public class ExistDoc {
   
     
    public static void main(String[] args) throws IOException {
   
     
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http"),
                new HttpHost("localhost", 9202, "http")
        ));
        GetRequest request = new GetRequest("book", "1");
        // 不需要获取source内容
        request.fetchSourceContext(new FetchSourceContext(false));
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
        client.close();
    }
}

5、更新文档

5.1、painless脚本更新

public static void main(String[] args) throws IOException {
   
     
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http"),
                new HttpHost("localhost", 9202, "http")
        ));
        UpdateRequest request = new UpdateRequest("book", "1");
        // 通过脚本更新
        Map<String, Object> params = Collections.singletonMap("name", "三国演义666");
        Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.name=params.name", params);
        request.script(script);
        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
        System.out.println("response.getId() = " + response.getId());
        System.out.println("response.getIndex() = " + response.getIndex());
        System.out.println("response.getVersion() = " + response.getVersion());
        if (response.getResult() == DocWriteResponse.Result.UPDATED) {
   
     
            System.out.println("更新成功!");
        }
        client.close();
    }

5.2、json更新

// 通过json更新
request.doc("{\"name\": \"三国演义\"}", XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);

5.3、Map更新

// 通过Map更新
Map<String, Object> docMap = new HashMap<>();
docMap.put("name", "三国演义888");
request.doc(docMap);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);

5.4、XContentBuilder更新

// 通过XContentBuilder更新
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
jsonBuilder.startObject();
jsonBuilder.field("name", "三国演义666");
jsonBuilder.endObject();
request.doc(jsonBuilder);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);

5.5、upsert更新

前面4种更新文档的方式,如果文档id不存在,找不到文档,就会抛出异常。除了更新前判断文档是否存在,还有另一只方法:在更新文档之前,我们可以使用upsert方法设置一个新文档,当文档不存在时添加这个新文档。

public class UpdateDoc {
   
     
    public static void main(String[] args) throws IOException {
   
     
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http"),
                new HttpHost("localhost", 9202, "http")
        ));
        UpdateRequest request = new UpdateRequest("book", "2");
        // 通过XContentBuilder更新
        XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        jsonBuilder.startObject();
        jsonBuilder.field("name", "三国演义666");
        jsonBuilder.endObject();
        request.doc(jsonBuilder);
        request.upsert("{\"name\": \"红楼梦\",\"author\": \"曹雪芹\"}", XContentType.JSON);
        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
        System.out.println("response.getId() = " + response.getId());
        System.out.println("response.getIndex() = " + response.getIndex());
        System.out.println("response.getVersion() = " + response.getVersion());
        if (response.getResult() == DocWriteResponse.Result.UPDATED) {
   
     
            System.out.println("更新成功!");
        }
        client.close();
    }
}

版权声明:

本文仅记录ElasticSearch学习心得,如有侵权请联系删除。
更多内容请访问原创作者:江南一点雨
*

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: