Elasticsearch基础—— API介绍(JAVA)

Elasticsearch JAVA API

下面内容是,官方文档的整理,想了解详细的内容可以访问官方文档:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html

客户端连接

Elasticsearch Java API 存在多种Client连接方式

  • TransportClient和RestClient是Elasticsearch原生的api
  • Spring Data Elasticsearch 为Spring整合的连接方式
  • Jest是Java社区开发的,是Elasticsearch的Java Http Rest客户端

目前几种连接方式:
TransportClient 后续版本中会被弃用

Jest因为是社区维护存在一定的延迟

Spring Data Elasticsearch为Spring整合的内容主要是为了配合Spring生态

Rest Client,官方维护

TransportClient 连接及操作

因为后续会被移除,所以只做简单了解,并没有介绍其他操作

依赖
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>7.1.1</version>
</dependency>
<dependency>
     <groupId>org.elasticsearch</groupId>
     <artifactId>elasticsearch</artifactId>
     <version>7.1.1</version>
</dependency>

创建连接的代码

    public TransportClient getClient(){
        TransportClient client = null;
        try {
            Settings settings = Settings.builder()
                    .put("client.transport.sniff", true)
                    .put("cluster.name", "name").build();
            client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(new TransportAddress(new InetSocketAddress("192.168.1.1", 9300)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

RestClient 连接及操作

因为现在多是使用此方式进行ES的连接,会主要介绍其相关数据操作的内容

客户端连接

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

创建连接的代码

    private RestHighLevelClient getClient() {
        RestHighLevelClient client = null;

        try {
            client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("192.168.1.1", 9300, "http")
                    )
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

Document APIs

Document APIs主要涉及些增删改查等操作,包括单条操作和多条操作

插入记录

Elasticsearch的数据插入主要是使用IndexRequest对象。目前Elasticsearch提供四种方式创建IndexRequest对象。

使用JSON形式

/**
     * 使用JSON形式
     * @return
     * @throws IOException
     */
    public IndexRequest IndexString() throws IOException {
        // 添加文档的请求
        // 三个参数 索引 文档id
        IndexRequest request = new IndexRequest("index", "id");

        String jsonString = "{" +
                "\"name\":\"key\"," +
                "\"age\":\"10\"," +
                "\"des\":\"this data\"" +
                "}";
        // 以字符串形式提供的数据
        request.source(jsonString, XContentType.JSON);

        return request;
    }

使用map形式

    public IndexRequest IndexMap() {
        //第二种方式: Map
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", "key");
        jsonMap.put("date", new Date());
        jsonMap.put("des", "this data");
        IndexRequest indexRequest = new IndexRequest("index", "id").source(jsonMap);
        return indexRequest;
    }

使用Builder建造器

    /**
     * 使用建造器
     * @return
     * @throws IOException
     */
    public IndexRequest indexBuilder() throws IOException {
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        builder.field("name", "key");
        builder.timeField("date" , new Date());
        builder.field("des", "this data");
        builder.endObject();
        IndexRequest indexRequest1 = new IndexRequest("index", "id")
                .source(builder);
        return indexRequest1;
    }

使用key-value形式

    /**
     * 使用key-value
     * @return
     * @throws IOException
     */
    public IndexRequest indexSource() throws IOException {
        IndexRequest indexRequest2 = new IndexRequest("index", "id")
                .source("name", "key",
                        "date", new Date(),
                        "des", "this data"
                );
        return indexRequest2;
    }

在完成IndexRequest创建之后需要进行文档插入的操作,目前ES提供了同步和异步的方式插入数据

同步的插入数据

    //同步执行
    IndexResponse indexResponse = RestClientUtils.client.index(request, RequestOptions.DEFAULT);

异步的插入数据

异步插入数据需要配置一个实现ActionListener接口的监听器,以方便监听结果的返回。

    //异步执行
    ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
        @Override
        public void onResponse(IndexResponse indexResponse) {

        }

        @Override
        public void onFailure(Exception e) {

        }
    };
    RestClientUtils.client.indexAsync(request, RequestOptions.DEFAULT, listener);

除了上面最基本的参数之外,ES也提供了更多的参数来实现不同的业务

        IndexRequest request = new IndexRequest();
        // 路由键
        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");
        // 设置文档获取通道名称
        request.setPipeline("pipeline");

获取数据(文档)

这里主要介绍的是单一数据的获取

Elasticsearch的数据获取主要是使用GetRequest对象。和插入数据类似,获取数据ES同样提供了同步和异步的方法;

    /**
     * 根据 id 获取数据
     * @throws Exception
     */
    public void get() throws Exception{
        GetRequest request = new GetRequest("index", "1");

        //同步执行
        GetResponse getResponse = RestClientUtils.client.get(request, RequestOptions.DEFAULT);

        //异步执行
        ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {


            @Override
            public void onResponse(GetResponse documentFields) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        //异步执行 listener的写法参照Index的异步执行的listener
        RestClientUtils.client.getAsync(request, RequestOptions.DEFAULT, listener);

        //Get Response 获取信息

        //抛出异常
    }

GetRequest同样提供了更多的参数,来丰富其业务

    // 禁用源检索,默认情况下启用
    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);

    // 为特定字段配置源排除
    String[] includes2 = Strings.EMPTY_ARRAY;
    String[] excludes2 = new String[]{"message"};
    FetchSourceContext fetchSourceContext2 =
            new FetchSourceContext(true, includes2, excludes2);
    request.fetchSourceContext(fetchSourceContext2);        
    
    
    // 配置路由
    request.routing("routing");
    // 配置偏好值
    request.preference("preference");
    // 将realtime设置为false
    request.realtime(false);
    // 在检索文档之前执行刷新(默认为false)
    request.refresh(true);
    // 版本
    request.version(2);
    // 版本类型
    request.versionType(VersionType.EXTERNAL);

数据(文档)验证

验证数据的存在和获取数据都是使用GetRequest对象进行操作,不过因为数据验证只会返回true或者false

   public void exists() throws Exception{
        GetRequest getRequest = new GetRequest("index", "1");

        //同步执行
        boolean exists = RestClientUtils.client.exists(getRequest, RequestOptions.DEFAULT);

        //异步执行
        ActionListener<Boolean> listener = new ActionListener<Boolean>() {


            @Override
            public void onResponse(Boolean aBoolean) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        //异步执行 listener的写法参照Index的
        RestClientUtils.client.existsAsync(getRequest, RequestOptions.DEFAULT, listener);

        if (exists){
            System.out.println("存在");
        }else {
            System.out.println("不存在");
        }
    }

有一点需要注意因为数据验证只会返回true和false所以,关闭对源数据的提取会消耗更少的资源

// 禁用fetching _source.
getRequest.fetchSourceContext(new FetchSourceContext(false)); 
删除数据(文档)

Elasticsearch的删除数据主要是使用DeleteResponse对象。和插入数据类似,获取数据ES同样提供了同步和异步的方法;

    /**
     * 根据id删除
     * @throws Exception
     */
    public void delete() throws Exception{
        DeleteRequest request = new DeleteRequest("posts", "1");

        //同步执行
        DeleteResponse deleteResponse = RestClientUtils.client.delete(request, RequestOptions.DEFAULT);

        //异步执行
        ActionListener<DeleteResponse> listener = new ActionListener<DeleteResponse>() {


            @Override
            public void onResponse(DeleteResponse deleteResponse1) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };

        //异步执行 listener参照index的
        RestClientUtils.client.deleteAsync(request, RequestOptions.DEFAULT, listener);

        //Delete Response
        String index = deleteResponse.getIndex();

        // 文档未找到
        if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {

        }

        //抛出异常

    }

额外的参数配置

    // 路由值
    request.routing("routing"); 
    // 设置超时
    request.timeout(TimeValue.timeValueMinutes(2)); 
    // 以字符串形式设置超时
    request.timeout("2m");  
    // 设置刷新策略
    request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
    // 字符串设置刷新策略    
    request.setRefreshPolicy("wait_for");   
    // 版本
    request.version(2); 
    // 版本类型
    request.versionType(VersionType.EXTERNAL); 
更新数据(文档)

Elasticsearch的更新数据主要是使用UpdateRequest对象。和插入数据类似,ES提供了多种方式创建UpdateRequest对象

用脚本更新

    public UpdateRequest getScript1() {
        UpdateRequest request = new UpdateRequest("index", "1");
        Map<String, Object> parameters = new HashMap<>(1);
        // 第一种方式:inline script
        Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.field += params.count", parameters);
        request.script(inline);
        return request;
    }

存储的脚本

    public UpdateRequest getScript2() {
        UpdateRequest request = new UpdateRequest("index", "1");
        Map<String, Object> parameters = new HashMap<>(1);
        Script stored = new Script(ScriptType.STORED, null, "increment-field", parameters);
        request.script(stored);
        return request;
    }

用部分文档更新


    // JSON形式
    public UpdateRequest getScript3() {
        UpdateRequest request = new UpdateRequest("index", "1");
        Map<String, Object> parameters = new HashMap<>(1);
        String jsonString = "{" +
                "\"updated\":\"2019-10-09"," +
                "\"reason\":\"data update \"" +
                "}";
        // 以JSON格式的字符串形式提供的部分文档
        request.doc(jsonString, XContentType.JSON);
        return request;
    }
    
    // map
    public UpdateRequest getScript4() {
        UpdateRequest request = new UpdateRequest("index", "1");
        Map<String, Object> parameters = new HashMap<>(1);
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("updated", new Date());
        jsonMap.put("reason", "daily update");
        request.doc(jsonMap);
        return request;
    }

    // builder
    public UpdateRequest getScript5() throws IOException {
        UpdateRequest request = new UpdateRequest("index", "1");
        Map<String, Object> parameters = new HashMap<>(1);
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        builder.timeField("updated", new Date());
        builder.field("reason", "daily update");
        builder.endObject();
        request.doc(builder);
        return request;
    }

    // key-value
    public UpdateRequest getScript6() {
        UpdateRequest request = new UpdateRequest("index",, "1");
        Map<String, Object> parameters = new HashMap<>(1);
        request.doc("updated", new Date(),
                "reason", "daily update");

        //upserts
        String jsonString1 = "{\"created\":\"2019-10-09\"}";
        request.upsert(jsonString1, XContentType.JSON);
        return request;
    }

执行更新的操作

   public void update() throws IOException {
        UpdateRequest request = getScript1();
        // 同步执行
        UpdateResponse updateResponse = RestClientUtils.client.update(request, RequestOptions.DEFAULT);

        // 异步执行
        ActionListener<UpdateResponse> listener = new ActionListener<UpdateResponse>() {


            @Override
            public void onResponse(UpdateResponse updateResponse1) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        // 异步执行, listener创建参考index的
        RestClientUtils.client.updateAsync(request, RequestOptions.DEFAULT, listener);

        // update Response
        GetResult result = updateResponse.getGetResult();
        if (result.isExists()) {
            String sourceAsString = result.sourceAsString();
            Map<String, Object> sourceAsMap = result.sourceAsMap();
            byte[] sourceAsBytes = result.source();
        } else {

        }

        //抛出异常
    }

至于更新的结果我们可以根据返回的UpdateResponse的结果来获取

// 我们使用getResult方法的返回内容可以判断更新结果
DocWriteResponse.Result result = updateResponse.getResult();

// 第一次创建文档的情况(upsert)
DocWriteResponse.Result.CREATED
// 文档更新
DocWriteResponse.Result.UPDATED
// 文档被删除的情况
DocWriteResponse.Result.DELETED
// 文档不受更新影响的情况,即没有对文档执行任何操作(noop)
DocWriteResponse.Result.NOOP

额外的参数

// 路由值
request.routing("routing"); 
// 超时
request.timeout(TimeValue.timeValueSeconds(1)); 
// 字符串设置的超时
request.timeout("1s"); 
// 设置刷新策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
// 字符串形式刷新策略
request.setRefreshPolicy("wait_for");
// 更新文档在更新操作的获取和索引之间被其他操作修改,重试的次数
request.retryOnConflict(3); 
// 启用源检索,默认情况下禁用
request.fetchSource(true);
// 为特定字段配置源包含
String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
request.fetchSource(
        new FetchSourceContext(true, includes, excludes)); 
// 为特定字段配置源排除
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"updated"};
request.fetchSource(
        new FetchSourceContext(true, includes, excludes)); 
// 禁用noop检测
request.detectNoop(false); 
// 指出无论文档是否存在,脚本都必须运行,即如果文档不存在,脚本负责创建文档。
request.scriptedUpsert(true); 
// 指示如果部分文档尚不存在,则必须将其用作upsert文档。
request.docAsUpsert(true); 
// 设置在继续更新操作之前必须活动的碎片副本数量。
request.waitForActiveShards(2); 
// ActiveShardCount的碎片副本数。可选值:ActiveShardCount.ALL, ActiveShardCount.ONE或者 ActiveShardCount.DEFAULT
request.waitForActiveShards(ActiveShardCount.ALL); 
批处理

ES提供了一个功能,我们可以使用单个请求执行多个索引的更新或删除,这就需要使用到BulkRequest

    BulkRequest request = new BulkRequest();

    //Other
    request.add(new DeleteRequest("posts", "3"));
    request.add(new UpdateRequest("posts", "2")
            .doc(XContentType.JSON, "other", "test"));
    request.add(new IndexRequest("posts")
            .source(XContentType.JSON, "field", "baz"));

我们可以使用这种方式将多个索引操作放到一个请求中。并且这些操作并不需要为同一类操作,可以是删除和更新放在一起。

批处理的执行

和上面的内容一样,其支持同步和异步两种方式

    //同步执行
    BulkResponse bulkResponses = RestClientUtils.client.bulk(request, RequestOptions.DEFAULT);

    //异步执行
    ActionListener<BulkResponse> listener = new ActionListener<BulkResponse>() {
        @Override
        public void onResponse(BulkResponse bulkResponse) {

        }

        @Override
        public void onFailure(Exception e) {

        }
    };
    RestClientUtils.client.bulkAsync(request, RequestOptions.DEFAULT, listener);

额外的参数

// 设置超时
request.timeout(TimeValue.timeValueMinutes(2)); 
request.timeout("2m"); 
// 设置刷新策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
request.setRefreshPolicy("wait_for"); 
// 设置在操作前需要活动的碎片副本数量
request.waitForActiveShards(2); 
// 作为动态硬装载提供的碎片副本数,可选:ActiveShardCount.ALL, ActiveShardCount.ONE或 ActiveShardCount.DEFAULT
request.waitForActiveShards(ActiveShardCount.ALL); 
// 用户子请求的全局管道
request.pipeline("pipelineId"); //用于所有子请求的全局管道标识
// 路由
request.routing("routingId"); 
// 设置请求的全局索引
BulkRequest defaulted = new BulkRequest("posts"); 

结果的处理

执行批处理后返回的BulkResponse包含有关已执行操作的信息,我们可以迭代每个结果来获取每条数据执行的内容

    //Bulk Response 批处理结果
    for (BulkItemResponse bulkItemResponse: bulkResponses){
        DocWriteResponse itemResponse = bulkItemResponse.getResponse();

            // 索引操作或创建操作
        if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
                || bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
            IndexResponse indexResponse = (IndexResponse) itemResponse;

            // 更新操作
        } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
            UpdateResponse updateResponse = (UpdateResponse) itemResponse;
            // 删除操作
        } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
            DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
        }
    }

批量数据获取

除了BulkResponse,ES还提供了MultiGetRequest对象,以实现一个请求,并行的处理多个查询操作

        MultiGetRequest request = new MultiGetRequest();
        request.add(new MultiGetRequest.Item("index","example_id"));
        request.add(new MultiGetRequest.Item("index", "another_id"));
        //optional arguments
        request.add(new MultiGetRequest.Item("index", "example_id") .fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE));

我们可以为一个请求添加多个操作子项,并且为其配置单独的参数。

执行获取

同样ES提供了同步和异步的获取方式

         //同步执行
        MultiGetResponse responses = RestClientUtils.client.mget(request, RequestOptions.DEFAULT);

        //异步执行
        ActionListener<MultiGetResponse> listener = new ActionListener<MultiGetResponse>() {

            @Override
            public void onResponse(MultiGetResponse multiGetItemResponses) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        //异步执行 listener参考Index的
        RestClientUtils.client.mgetAsync(request, RequestOptions.DEFAULT, listener);

结果的处理

返回的内容是一个MultiGetItemResponse列表,按请求的顺序排列在GetResponse中。其操作很类似一个普通的GetResponse。

    //Multi Get Response
    MultiGetItemResponse firstItem = responses.getResponses()[0];
    GetResponse firstGet = firstItem.getResponse();
    if (firstGet.isExists()) {
        // 业务
    }

额外的参数设置

// 禁用源检索,默认情况下启用
request.add(new MultiGetRequest.Item("index", "example_id")
    .fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE));  
    
// 为特定字段配置源包含
String[] includes = new String[] {"foo", "*r"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext =
        new FetchSourceContext(true, includes, excludes);
request.add(new MultiGetRequest.Item("index", "example_id")
    .fetchSourceContext(fetchSourceContext));  
    
// 为特定字段配置源排除
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[] {"foo", "*r"};
FetchSourceContext fetchSourceContext =
        new FetchSourceContext(true, includes, excludes);
request.add(new MultiGetRequest.Item("index", "example_id")
    .fetchSourceContext(fetchSourceContext));  
// 配置特定存储字段的检索(要求字段在映射中单独存储)
request.add(new MultiGetRequest.Item("index", "example_id")
    .storedFields("foo"));  
// 设置路由
request.add(new MultiGetRequest.Item("index", "with_routing")
    .routing("some_routing"));    
// 设置版本 以及版本类似
request.add(new MultiGetRequest.Item("index", "with_version")
    .versionType(VersionType.EXTERNAL)  /
    .version(10123L));           
// preference, realtime和refresh可以在主请求上设置,但不能在任何项目上设置:
// 偏好值
request.preference("some_preference");  
// 将实时标志设置为false(默认true)
request.realtime(false);
// 在检索文档之前执行刷新(默认false)
request.refresh(true); 


个人水平有限,上面的内容可能存在没有描述清楚或者错误的地方,假如开发同学发现了,请及时告知,我会第一时间修改相关内容。假如我的这篇内容对你有任何帮助的话,麻烦给我点一个赞。你的点赞就是我前进的动力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值