ES高级客户端文档操作实战

在Elasticsearch中,高级客户端支持以下文档相关的API:

(1)Single document APIs——单文档操作API。(2)Index API——文档索引API。(3)Get API——文档获取API。(4)Exists API——文档存在性判断API。(5)Delete API——文档删除API。(6)Update API——文档更新API。(7)Term Vectors API——词向量API。(8)Bulk API——批量处理API。(9)Multi-Get API——多文档获取API。(10)ReIndex API——重新索引API。(11)Update By Query API——查询更新API。(12)Delete By Query API——查询删除API。(13)Multi Term Vectors API——多词条向量API。

其中,前7项较为简单,后6项较为复杂,因此我们将用两章介绍这些API的使用。

文档

在Elasticsearch中,使用JavaScript对象符号(JavaScript Object Notation),作为文档序列化格式,也就是我们常说的JSON。JSON对象由键值对组成,键(key)是字段或属性名称,值(value)可以是多种类型,如字符串、数字、布尔值、一个对象、值数组、日期的字符串、地理位置对象等。

例如:

在Elasticsearch中,存储并索引的JSON数据被称为文档,文档会以唯一ID进行标识并存储于Elasticsearch中。文档不仅有自身的键值对数据信息,还包含了元数据,即关于文档的信息。

文档一般包含三个必需的元数据信息:

(1)index:文档存储的数据结构,即索引。

(2)type:文档代表的对象类型。

(3)ID:文档的唯一标识。

index表示的是索引。这有点类似于开发人员常用的关系数据库中的“数据库”的概念,索引表示的是Elasticsearch存储和索引关联数据的数据结构。需要指出的是,文档数据最终是被存储和索引在分片中的,索引多个分片存储的逻辑空间。

type表示的是文档代表的对象类型。在实际使用时,type的命名是有一定规范的,名字中的字母可以是大写,也可以是小写;但不能包含下画线或逗号。

id表示的是文档的唯一标识,如ID,文档标识会以字符串形式出现。当在Elasticsearch中创建一个文档时,用户既可以自定义id,也可以让Elasticsearch自动生成。

id、index和type三个元素组合使用时,可以在Elasticsearch中唯一标识一个文档。

文档操作

Elasticsearch是面向文档的,它可以存储整个文档。但Elasticsearch对文档的操作不仅限于存储,Elasticsearch还会索引每个文档的内容使之可以被搜索。在Elasticsearch中,用户可以对文档数据进行索引、搜索、排序和过滤等操作,而这也是Elasticsearch能够执行复杂的全文搜索的原因之一。下面一一介绍在Elasticsearch中对文档操作的各类API。

文档索引操作

1-构建请求

es新增文档案例:_doc是默认的文档类型,es7之后去除文档类型概念。

    构建请求时,设置文档通过其index、type和ID确定其唯一存储所在。对于ID,用户可以自己提供一个ID,或者使用索引API自动生成。在IndexRequest中,除三个必选参数外,还有一些可选参数。可选参数包含路由、超时时间、版本、版本类型和索引管道名称等。

2-执行索引文档请求

    在JSON文档构建后,即可执行索引文档请求。在Elasticsearch中,索引文档有两种方式,即同步方式和异步方式。

    同步方式 以同步方式执行IndexRequest时,客户端必须等待返回结果IndexResponse。在收到IndexResponse之后,客户端方可继续执行代码。

                    restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);

    异步方式 当以异步方式执行IndexRequest时,高级客户端不必同步等待请求结果的返回,可以直接向接口调用方返回异步接口执行成功的结果。为了处理异步返回的响应信息或处理在请求执行过程中引发的异常信息,用户需要指定监听器ActionListener。如果请求执行成功,则调用ActionListener中的onResponse方法进行相应逻辑的处理。如果请求执行失败,则调用ActionListener中的onFailure方法进行相应逻辑的处理。

                    restHighLevelClient.indexAsync(indexRequest, RequestOptions.DEFAULT, actionListener);

具体代码:

import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.VersionType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.io.IOException;

@RestController
@RequestMapping(value = "/rest/")
public class EsRestController {

    /**
     * 高级客户端
     */
    private RestHighLevelClient restHighLevelClient;

    /**
     * 客户端初始化
     */
    @PostConstruct
    public void initClient() {
        restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("8.129.210.66", 9200, "http")));
        System.out.println(String.format("客户端初始化 restHighLevelClient=(%s)", restHighLevelClient.toString()));
    }

    public void closeEs() {
        try {
            restHighLevelClient.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(String.format("关闭客户端异常 ex=(%s)", e.getMessage()));
        }
    }

    @RequestMapping(value = "/add-index")
    public String addDoc() {

        // 1-构建请求
        IndexRequest indexRequest = new IndexRequest("item"); // 设置索引名称
        indexRequest.id("1"); // 设置文档ID
        indexRequest.source("{" + "\"name\": \"商品2\","
                + "\"price\": \"10\"," + "\"number\": \"10\"" + "}", XContentType.JSON); // 设置文档内容

        // 在IndexRequest中,除三个必选参数外,还有一些可选参数。可选参数包含路由、超时时间、版本、版本类型和索引管道名称等

        // 设置超时时间
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        // 设置超时策略
        indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
        // 设置版本 创建的时候不支持设置版本号
        // indexRequest.version(Long.valueOf("1"));
        // 设置版本类型
        // indexRequest.versionType(VersionType.EXTERNAL);
        // 设置操作类型
        indexRequest.opType(DocWriteRequest.OpType.CREATE);
        // 在索引文档之前要执行的接收的管道的名称
        // indexRequest.setPipeline("pipeline");

        // 同步
        index(indexRequest);
        // 异步
        // indexAsync(indexRequest);

        return null;
    }

    /**
     * 异步执行请求
     *
     * @param indexRequest
     */
    private void indexAsync(IndexRequest indexRequest) {
        try {
            ActionListener actionListener = new ActionListener<IndexResponse>() {
                @Override
                public void onResponse(IndexResponse indexResponse) {
                    System.out.println("执行成功");
                }
                @Override
                public void onFailure(Exception e) {
                    System.out.println("执行失败 + " + e.getMessage());
                }
            };
            restHighLevelClient.indexAsync(indexRequest, RequestOptions.DEFAULT, actionListener);
        } catch (Exception e) {
            System.out.println("执行失败1");
        }
    }

    /**
     * 同步执行请求
     *
     * @param indexRequest
     */
    private IndexResponse index(IndexRequest indexRequest) {
        try {
            return restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            System.out.println("执行失败" + e.getMessage());
            return null;
        }
    }


}

文档索引查询

1-构建文档索引查询请求

在执行文档索引查询请求前,需要构建文档索引查询请求,即GetRequest。GetRequest有两个必选参数,即索引名称和文档ID。

        GetRequest getRequest = new GetRequest("item", "2");

在构建GetRequest的过程中,可以选择其他可选参数进行相应的配置。可选参数有禁用源检索、为特定字段配置源包含关系、为特定字段配置源排除关系、为特定存储字段配置检索、配置路由值、配置偏好值、配置在检索文档之前执行刷新、配置版本号、配置版本类型等

2-执行文档索引查询请求

在GetRequest构建后,即可执行文档索引查询请求。与文档索引请求类似,文档索引查询请求也有同步和异步两种执行方式。

同步方式  当以同步方式执行GetRequest时,客户端会等待Elasticsearch服务器返回的查询结果GetResponse。在收到GetResponse后

        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);

异步方式 当以异步方式执行GetRequest时,高级客户端不必同步等待请求结果的返回,可以直接向接口调用方返回异步接口执行成功的结果。为了处理异步返回的响应信息或处理在请求执行过程中引发的异常信息,用户需要指定监听器ActionListener。如果请求执行成功,则调用ActionListener中的onResponse方法进行相应逻辑的处理。如果请求执行失败,则调用ActionListener中的onFailure方法进行相应逻辑的处理。

        restHighLevelClient.getAsync(getRequest, RequestOptions.DEFAULT, actionListener);

具体代码

package com.example.luu.es_demo.es;


import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.io.IOException;

@RestController
@RequestMapping(value = "/rest/")
public class EsRestController {

    /**
     * 高级客户端
     */
    private RestHighLevelClient restHighLevelClient;

    /**
     * 客户端初始化
     */
    @PostConstruct
    public void initClient() {
        restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("8.129.210.66", 9200, "http")));
        System.out.println(String.format("客户端初始化 restHighLevelClient=(%s)", restHighLevelClient.toString()));
    }

    public void closeEs() {
        try {
            restHighLevelClient.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(String.format("关闭客户端异常 ex=(%s)", e.getMessage()));
        }
    }


    @RequestMapping(value = "/query-index")
    public String queryDoc() {

        // 1-构建请求
        GetRequest getRequest = new GetRequest("item", "2");

        // 在构建GetRequest的过程中,可以选择其他可选参数进行相应的配置。可选参数有禁用源检索、为特定字段配置源包含关系、
        // 为特定字段配置源排除关系、为特定存储字段配置检索、配置路由值、配置偏好值、配置在检索文档之前执行刷新、配置版本号、配置版本类型等

        // 同步
        indexGet(getRequest);
        // 异步
        // indexAsyncGet(getRequest);

        return null;
    }

    /**
     * 异步执行请求
     *
     * @param getRequest
     */
    private void indexAsyncGet(GetRequest getRequest) {
        try {
            ActionListener actionListener = new ActionListener<GetResponse>() {
                @Override
                public void onResponse(GetResponse getResponse) {
                    System.out.println("结果" + getResponse.getSourceAsString());
                }

                @Override
                public void onFailure(Exception e) {
                    System.out.println("执行失败 + " + e.getMessage());
                }
            };
            restHighLevelClient.getAsync(getRequest, RequestOptions.DEFAULT, actionListener);
        } catch (Exception e) {
            System.out.println("执行失败" + e.getMessage());
        }
    }

    /**
     * 同步执行请求
     *
     * @param getRequest
     */
    private void indexGet(GetRequest getRequest) {
        try {
            GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
            System.out.println("结果" + getResponse.getSourceAsString());
        } catch (IOException e) {
            System.out.println("执行失败" + e.getMessage());
        }

    }
}

文档存在性校验

Elasticsearch还提供了校验文档是否存在于某索引中的接口API,即Exists API。当调用该接口时,如果被验证的文档存在,则Exists API会返回true,否则返回false。这个接口特别适合只检查某文档是否存在的场景。

1-构建文档存在性校验请求

Exists API依赖于GetRequest的实例,这点很像文档索引查询API,即Get API。同理,在Exists API中也会支持GetRequest的所有可选参数。由于在Exists API的返回结果中只有布尔型的值,即true或false,因此建议用户关闭提取源和任何存储字段,以使请求的构建是轻量级的。

       // 1-构建请求
       GetRequest getRequest = new GetRequest("item", "2");
       // 禁用提取源
       getRequest.fetchSourceContext(new FetchSourceContext(false));
       // 禁用提取存储字段
       getRequest.storedFields("_none_");

2.执行文档存在性校验请求

在GetRequest构建后,即可执行文档存在性校验请求。与文档索引请求和文档索引查询请求类似,文档存在性校验请求也有同步和异步两种执行方式。

同步方式 当以同步方式执行文档存在性校验请求时,客户端会等待Elasticsearch服务器返回的查询结果。在收到查询结果后,客户端会继续执行相关的逻辑代码。

        Boolean flag = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);

异步方式 当以异步方式执行GetRequest时,高级客户端不必同步等待请求结果的返回,可以直接向接口调用方返回异步接口执行成功的结果。为了处理异步返回的响应信息或处理在请求执行过程中引发的异常信息,用户需要指定监听器ActionListener。在请求执行后,如果请求执行成功,则调用ActionListener类中的onResponse方法进行相关逻辑的处理;如果请求执行失败,则调用ActionListener类中的onFailure方法进行相关逻辑的处理。

        restHighLevelClient.existsAsync(getRequest, RequestOptions.DEFAULT, actionListener);

具体代码

package com.example.luu.es_demo.es;


import com.sun.org.apache.xpath.internal.operations.Bool;
import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.io.IOException;

@RestController
@RequestMapping(value = "/rest/")
public class EsRestController {

    /**
     * 高级客户端
     */
    private RestHighLevelClient restHighLevelClient;

    /**
     * 客户端初始化
     */
    @PostConstruct
    public void initClient() {
        restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("8.129.210.66", 9200, "http")));
        System.out.println(String.format("客户端初始化 restHighLevelClient=(%s)", restHighLevelClient.toString()));
    }

    public void closeEs() {
        try {
            restHighLevelClient.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(String.format("关闭客户端异常 ex=(%s)", e.getMessage()));
        }
    }

    @RequestMapping(value = "/exists-index")
    public String existsDoc() {

        // 1-构建请求
        GetRequest getRequest = new GetRequest("item", "2");

        // 禁用提取源
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        // 禁用提取存储字段
        getRequest.storedFields("_none_");

        // 同步
        indexExist(getRequest);
        // 异步
        indexAsyncExist(getRequest);

        return null;
    }

    /**
     * 异步执行请求
     *
     * @param getRequest
     */
    private void indexAsyncExist(GetRequest getRequest) {
        try {
            ActionListener actionListener = new ActionListener<Boolean>() {
                @Override
                public void onResponse(Boolean exist) {
                    System.out.println("结果" + exist);
                }

                @Override
                public void onFailure(Exception e) {
                    System.out.println("执行失败 + " + e.getMessage());
                }
            };
            restHighLevelClient.existsAsync(getRequest, RequestOptions.DEFAULT, actionListener);
        } catch (Exception e) {
            System.out.println("执行失败" + e.getMessage());
        }
    }

    /**
     * 同步执行请求
     *
     * @param getRequest
     */
    private void indexExist(GetRequest getRequest) {
        try {
            Boolean flag = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
            System.out.println("结果" + flag);
        } catch (IOException e) {
            System.out.println("执行失败" + e.getMessage());
        }

    }
}

删除文档索引

Elasticsearch提供了在索引中删除文档接口的API。

1-构建删除文档索引

请求在执行删除文档索引请求前,需要构建删除文档索引请求,即DeleteRequest。在DeleteRequest中有两个必选参数,即索引名称和文档ID。

// 1-构建请求
DeleteRequest deleteRequest = new DeleteRequest("item", "2");

在DeleteRequest的构建过程中,可以设置一些可选参数。可选参数有路由设置参数、超时设置参数、刷新策略设置参数、版本设置参数和版本类型设置参数等。

2-执行删除文档索引请求

在DeleteRequest构建后,即可执行删除文档索引请求。与文档索引请求类似,删除文档索引请求也有同步和异步两种执行方式。

同步方式 当以同步方式执行删除文档索引请求时,客户端会等待Elasticsearch服务器返回的查询结果DeleteResponse。在收到DeleteResponse后,客户端继续执行相关的逻辑代码。

DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);

异步方式 当以异步方式执行删除文档索引请求时,高级客户端不必同步等待请求结果的返回,可以直接向接口调用方返回异步接口执行成功的结果。在删除文档索引请求执行后,如果请求执行成功,则调用ActionListener类中的onResponse方法进行相关逻辑的处理;如果请求执行失败,则调用ActionListener类中的onFailure方法进行相关逻辑的处理。

restHighLevelClient.deleteAsync(deleteRequest, RequestOptions.DEFAULT, actionListener);

具体代码:

@RequestMapping(value = "/del-index")
    public String delDoc() {

        // 1-构建请求
        DeleteRequest deleteRequest = new DeleteRequest("item", "2");

        // 同步
        indexDel(deleteRequest);
        // 异步
        // indexAsyncDel(deleteRequest);

        return null;
    }

    /**
     * 异步执行请求
     *
     * @param deleteRequest
     */
    private void indexAsyncDel(DeleteRequest deleteRequest) {
        try {
            ActionListener actionListener = new ActionListener<Boolean>() {
                @Override
                public void onResponse(Boolean exist) {
                    System.out.println("结果" + exist);
                }

                @Override
                public void onFailure(Exception e) {
                    System.out.println("执行失败 + " + e.getMessage());
                }
            };
            restHighLevelClient.deleteAsync(deleteRequest, RequestOptions.DEFAULT, actionListener);
        } catch (Exception e) {
            System.out.println("执行失败" + e.getMessage());
        }
    }

    /**
     * 同步执行请求
     *
     * @param deleteRequest
     */
    private void indexDel(DeleteRequest deleteRequest) {
        try {
            DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            System.out.println("结果" + deleteResponse);
        } catch (IOException e) {
            System.out.println("执行失败" + e.getMessage());
        }
    }

更新文档索引

Elasticsearch提供了在索引中更新文档接口的API。

1-构建更新文档索引

请求在执行更新索引文档请求前,需要构建更新文档索引请求,即UpdateRequest。UpdateRequest有两个必选参数,即索引名称和文档ID。

// 1-构建请求
UpdateRequest updateRequest = new UpdateRequest("item", "1").doc("{" + "\"name\": \"商品222222住过你家祖国强大\","
        + "\"price\": \"10\"," + "\"number\": \"10\"" + "}", XContentType.JSON);

在构建UpdateRequest的过程中,还需要配置一些可选参数。可选参数有路由设置参数和超时设置参数,另外,还可以配置并发对同一文档更新时的重试次数。此外,用户可以配置启用源检索参数,为特定字段配置源包含关系,为特定字段配置源排除关系。

2-执行更新文档索引请求

在UpdateRequest构建后,即可执行更新文档索引请求。与文档索引请求类似,更新文档索引请求也有同步和异步两种执行方式。

同步方式 当以同步方式执行更新文档索引请求时,客户端会等待Elasticsearch服务器返回的查询结果UpdateResponse。在收到UpdateResponse后,客户端继续执行相关的逻辑代码。

UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);

异步方式 当以异步方式执行UpdateRequest时,高级客户端不必同步等待请求结果的返回,可以直接向接口调用方返回异步接口执行成功的结果。在UpdateRequest执行后,如果请求执行成功,则调用ActionListener类中的onResponse方法执行相关逻辑;如果请求执行失败,则调用ActionListener类中的onFailure方法执行相关逻辑。

restHighLevelClient.updateAsync(updateRequest, RequestOptions.DEFAULT, actionListener);

具体代码

    @RequestMapping(value = "/update-index")
    public String dpdateDoc() {

        // 1-构建请求
        UpdateRequest updateRequest = new UpdateRequest("item", "1").doc("{" + "\"name\": \"商品222222住过你家祖国强大\","
                + "\"price\": \"10\"," + "\"number\": \"10\"" + "}", XContentType.JSON);

        // 同步
        indexUpdate(updateRequest);
        // 异步
        // indexAsyncUpdate(updateRequest);

        return null;
    }

    /**
     * 异步执行请求
     *
     * @param updateRequest
     */
    private void indexAsyncUpdate(UpdateRequest updateRequest) {
        try {
            ActionListener actionListener = new ActionListener<Boolean>() {
                @Override
                public void onResponse(Boolean exist) {
                    System.out.println("结果" + exist);
                }

                @Override
                public void onFailure(Exception e) {
                    System.out.println("执行失败 + " + e.getMessage());
                }
            };
            restHighLevelClient.updateAsync(updateRequest, RequestOptions.DEFAULT, actionListener);
        } catch (Exception e) {
            System.out.println("执行失败" + e.getMessage());
        }
    }

    /**
     * 同步执行请求
     *
     * @param updateRequest
     */
    private void indexUpdate(UpdateRequest updateRequest) {
        try {
            UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            System.out.println("结果" + updateResponse);
        } catch (IOException e) {
            System.out.println("执行失败" + e.getMessage());
        }
    }

其实高级客户端还提供了很多API,具体的我们可以查看文档进行使用,主要我们还是需要了解es的特性。

 

 

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值