草庐IT

Elasticsearch Java REST Client 初始化、添加索引及数据

小丑的忧伤 2023-12-11 原文

上一篇:Elasticsearch基础与概念
下一篇:Elasticsearch Java REST Client 查询
所有代码均为参考官方文档:官方文档

原文说明

Java 高级 REST 客户端在 Java 低级 REST 客户端之上工作。它的主要目标是公开 API 特定的方法,这些方法接受请求对象作为参数并返回响应对象,以便由客户端自己处理请求编组和响应解组。

每个 API都可以同步或异步调用。同步方法返回一个响应对象,而名称以async后缀结尾的异步方法需要一个侦听器参数,一旦收到响应或错误,就会通知该侦听器参数(在低级客户端管理的线程池上)。

Java High Level REST Client 依赖于 Elasticsearch 核心项目。它接受与相同的请求参数TransportClient并返回相同的响应对象。

java API 文档:JAVA doc
低版本的:Java REST Client
高版本的:Elasticsearch Java API Client

注意安装版本要与客户端引入依赖保持一致,否则会出现版本问题
高版本的初始化方式与低版本的不一样,建议参考对应版本的文档
高版本的依赖会出现一部分jakarta.json加载不到,可引入下面依赖来解决

<dependency>
    <groupId>org.eclipse.parsson</groupId>
    <artifactId>jakarta.json</artifactId>
    <version>1.0.0</version>
</dependency>

Elasticsearch Maven

# 所需的最低 Java 版本是1.8
# 所需依赖
<dependency>
     <groupId>org.elasticsearch.client</groupId>
     <artifactId>elasticsearch-rest-high-level-client</artifactId>
     <version>6.7.2</version>
 </dependency>
 <dependency>
     <groupId>org.elasticsearch</groupId>
     <artifactId>elasticsearch</artifactId>
     <version>6.7.2</version>
 </dependency>

初始化客户端

package com.wdz.es.config.es;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticsearchConfig {
    @Value("${elasticsearch.hosts}")
    private String hosts;
    @Value("${elasticsearch.username}")
    private String username;
    @Value("${elasticsearch.password}")
    private String password;

    /**
     * 有密码初始化
     *
     * @return
     */
    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        // 设置密码
        BasicCredentialsProvider provider = new BasicCredentialsProvider();
        provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
                RestClient.builder(setHost()).setHttpClientConfigCallback(
                        new RestClientBuilder.HttpClientConfigCallback() {
                            @Override
                            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                                httpAsyncClientBuilder.disableAuthCaching();
                                return httpAsyncClientBuilder.setDefaultCredentialsProvider(provider);
                            }
                        }
                ));
        return restHighLevelClient;
    }

    /**
     * 无密码初始化
     * @return
     */
    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(setHost()));
        return restHighLevelClient;
    }

    private HttpHost[] setHost(){
        String[] split = hosts.split(",");
        HttpHost[] hhs = new HttpHost[split.length];
        for (int i = 0; i < split.length; i++) {
            String host = split[i];
            String[] ht = host.split(":");
            hhs[i] = new HttpHost(ht[0], Integer.parseInt(ht[1]), "http");
        }
        return hhs;
    }
}

参数hosts可以多个用户逗号分隔,在代码中进行解析,格式:ip:port

校验和创建索引

/**
 * 校验索引是否存在,如果不存在进行创建
 */
private boolean checkCreate(String index) throws IOException {
    GetIndexRequest request = new GetIndexRequest(index);
    boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
    if (!exists) {
        CreateIndexRequest create = new CreateIndexRequest(index);
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(create, RequestOptions.DEFAULT);
        System.out.println(JSONObject.toJSONString(createIndexResponse));
    }
    return exists;
}
// 该方法可以放在业务实现类中,在服务启动时校验一次
@PostConstruct
public void checkCreate(){
   // 索引参数,相当于数据库中的一张表
   String index = "edu-app-user";
   GetIndexRequest request = new GetIndexRequest(index);
   try {
       boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
       if (!exists) {
           CreateIndexRequest create = new CreateIndexRequest(index);
           CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(create, RequestOptions.DEFAULT);
           System.out.println(JSONObject.toJSONString(createIndexResponse));
       }
   } catch (IOException e) {
       e.printStackTrace();
   }
}

同步添加数据

为了方便调试,所有接口使用get方式

# 方式一:使用map方式进行添加数据,推荐使用
@GetMapping("add")
public IndexResponse add(String id, String name, String mobile, Integer age) {
    Map<String, Object> jsonMap = new HashMap<>();
    jsonMap.put("id", id);
    jsonMap.put("name", name);
    jsonMap.put("mobile", mobile);
    jsonMap.put("age", age);
    // 参数1: 索引,同一个文档(或者说数据库中的表名)唯一,
    // 参数2:文档类型,在高版本中已经优化,可不需要该参数,
    // 参数3:id,内部id参数值,也可默认,该参数是String类型
    IndexRequest request = new IndexRequest("edu-app-user", "doc", id).source(jsonMap);
    // 选填数据
    request.opType(DocWriteRequest.OpType.CREATE);
    IndexResponse response = null;
    try {
        // 校验索引是否存在,否则
        checkCreate("edu-app-user");
        // 执行添加,默认的请求操作方式
        response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}
# 方式二 拼接json方式,该方式不推荐使用,容易出错
@GetMapping("add2")
public IndexResponse add2(String id, String name, String mobile, Integer age) {
    IndexRequest request = new IndexRequest("edu-app-user", "doc", id);
    String jsonString = "{" +
                "\"id\":" + id + "," +
                "\"name\":" + name + "," +
                "\"mobile\":" + mobile + "," +
                "\"age\":" + age +
                "}";
    request.source(jsonString, XContentType.JSON.mediaType());
    IndexResponse response = null;
    try {
        response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}
# XContentType 中定义多种类型,默认是XContentType.JSON = "application/json",会出现编码问题
# 方式三 推荐使用,更简洁易读
@GetMapping("add3")
public IndexResponse add3(String id, String name, String mobile, Integer age) throws IOException {
    XContentBuilder builder = XContentFactory.jsonBuilder();
    builder.startObject();
    {
        builder.field("id", id);
        builder.field("name", name);
        builder.field("mobile", mobile);
        builder.timeField("updateTime", new Date());
        builder.field("age", age);
    }
    builder.endObject();
    IndexRequest request = new IndexRequest("edu-app-user", "doc", id);
    request.source(builder);
    IndexResponse response = null;
    try {
        response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}
# 方式四:直接在request.source()中进行参数操作
@GetMapping("add4")
public IndexResponse add4(String id, String name, String mobile, Integer age) {
    IndexRequest request = new IndexRequest("edu-app-user", "doc", id)
            .source("id", id,
                    "name", name,
                    "age", age,
                    "mobile", mobile);
    IndexResponse response = null;
    try {
        response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}
# 其他可选方法
# 过期时间指定,两种方式
request.timeout(TimeValue.timeValueSeconds(1)); 
request.timeout("1s");
# 刷新策略
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
request.setRefreshPolicy("wait_for");  

异步添加数据

同步与异步区别是方法上:(springboot 中的es版本和显式引入的依赖会出现冲突问题,直接显式定义es版本即可解决)

<properties>
   <elasticsearch.version>6.7.2</elasticsearch.version>
</properties>
@GetMapping("addAsync")
public void addAsync(String id, String name, String mobile, Integer age) {
     IndexRequest request = new IndexRequest("edu-app-user", "doc", id)
             .source("id", id,
                     "name", name,
                     "age", age,
                     "mobile", mobile);
     restHighLevelClient.indexAsync(request, RequestOptions.DEFAULT, new EduAppUserListener());
 }
# 监听类
package com.wdz.es.config.es;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.index.IndexResponse;

public class EduAppUserListener implements ActionListener<IndexResponse> {
    @Override
    public void onResponse(IndexResponse response) {
        System.out.println("异步保存成功:"+ response);
    }

    @Override
    public void onFailure(Exception e) {
        System.out.println("异步保存失败:"+ e.getMessage());
    }
}

上一篇:Elasticsearch基础与概念
下一篇:Elasticsearch Java REST Client 查询

有关Elasticsearch Java REST Client 初始化、添加索引及数据的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 将 Bootstrap Less 添加到 Sinatra - 2

    我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  7. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  8. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  9. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  10. ruby - 可以通过多少种方法将方法添加到 ruby​​ 对象? - 2

    当谈到运行时自省(introspection)和动态代码生成时,我认为ruby​​没有任何竞争对手,可能除了一些lisp方言。前几天,我正在做一些代码练习来探索ruby​​的动态功能,我开始想知道如何向现有对象添加方法。以下是我能想到的3种方法:obj=Object.new#addamethoddirectlydefobj.new_method...end#addamethodindirectlywiththesingletonclassclass这只是冰山一角,因为我还没有探索instance_eval、module_eval和define_method的各种组合。是否有在线/离线资

随机推荐