前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch-Java

Elasticsearch-Java

作者头像
乐心湖
发布2021-01-29 07:09:29
7790
发布2021-01-29 07:09:29
举报
文章被收录于专栏:MyTechnologyMyTechnology

Java操作方案

直接使用 HTTP

直接使用 HTTP 请求,去操作 Es。HTTP 请求工具,可以使用 Java 自带的 HttpUrlConnection,也可以使用一些 HTTP 请求库,例如 HttpClientOKHttp、Spring 中的 RestTemplate 都可以。这种方式有一个弊端,就是要自己组装请求参数,自己去解析响应的 JSON。

Low Level REST Client

用于 Es 的官方的低级客户端。这种方式允许通过 HTTP 与 Es 集群进行通信,但是请求时候的 JSON 参数和响应的 JSON 参数交给用户去处理。这种方式好处就是兼容所有的 Es 版本。但是就是数据处理比较麻烦。

High Level REST Client

用户 Es 的官方的高级客户端。这种方式允许通过 HTTP 与 Es 集群进行通信,它是基于 Low Level REST Client,但是提供了很多 API,开发者不需要自己去组装参数,也不需要自己去解析响应 JSON 。这种方式使用起来更加直接。但是需要注意,这种方式,所使用的依赖库的版本要和 Es 对应。

TransportClient

TransportClient 在 Es7 中已经被弃用,在 Es8 中将被完全删除。

下面我们将通过 High Level REST Client 作为演示。

添加 Maven 依赖,注意:使用该依赖需要确保版本跟 elasticsearch 版本一致

代码语言:javascript
复制
<dependency>
  <groupId>org.elasticsearch.client</groupId>
  <artifactId>elasticsearch-rest-high-level-client</artifactId>
  <version>7.4.2</version>
</dependency>

注意:如果你是在 SpringBoot 环境下学习测试,必须查看版本是否正确。例如下面这种情况,既有7.6.2又有7.4.2,原因就是 SpringBoot 帮我们管理了一个 elasticsearch 版本,只需要在 pom 中指定版本,覆盖掉 SpringBoot 的配置即可。

创建配置类,这里我就起名 LaketradingElasticsearchConfig

代码语言:javascript
复制
@Configuration
public class LaketradingElasticsearchConfig {

  public static final RequestOptions COMMON_OPTIONS;
  static {
    RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
    //builder.addHeader("Authorization", "Bearer " + TOKEN);
    //builder.setHttpAsyncResponseConsumerFactory(
    //        new HttpAsyncResponseConsumerFactory
    //                .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
    COMMON_OPTIONS = builder.build();
  }

  @Bean
  public RestHighLevelClient esRestClient(){
    return new RestHighLevelClient(
      RestClient.builder(
        new HttpHost("192.168.56.10", 9200, "http")));
  }
}

官方的API文档地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-supported-apis.html

建议读一遍官方文档,了解一个大概,用时查阅即可。

举例测试

接下来我们对之前在高级检索博客中的一些例子,在 java 中用代码实现。

首先是一个匹配的问题,我们对 "address" = "mill lane" 的结果进行筛选。

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class LaketradingSearchApplicationTests {

  @Autowired
  private RestHighLevelClient client;

  @Test
  public void searchData() throws IOException {
    // 创建索引请求
    SearchRequest searchRequest = new SearchRequest();
    // 指定索引
    searchRequest.indices("bank");
    // 构造索引条件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.matchQuery("address","mill lane"));
    System.out.println("检索条件:" + sourceBuilder.toString());
    searchRequest.source(sourceBuilder);
    // 执行
    SearchResponse searchResponse = client.search(searchRequest, LaketradingElasticsearchConfig.COMMON_OPTIONS);
    System.out.println(searchResponse.toString());
  }
}

在控制台打印出来的结果可以看出跟我们之前测试一模一样。接下来我们去测试聚合检索。

结果:31岁的人有61个,他们的平均工资为28312。

代码语言:javascript
复制
"aggregations" : {
  "ageAgg" : {
    "doc_count_error_upper_bound" : 0,
    "sum_other_doc_count" : 463,
    "buckets" : [
      {
        "key" : 31,
        "doc_count" : 61,
        "balanceAvg" : {
          "value" : 28312.918032786885
        }
      },
      ...
    ]
  }
}

java代码

代码语言:javascript
复制
@Test
public void searchData() throws IOException {
  // 创建索引请求
  SearchRequest searchRequest = new SearchRequest();
  // 指定索引
  searchRequest.indices("bank");
  // 构造索引条件
  SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  // 聚合条件工具类
  AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
  TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").subAggregation(balanceAvg);
  sourceBuilder.aggregation(ageAgg);
  // 因为这次是聚合检索,我们就不看查询结果了,直接看聚合结果。
  sourceBuilder.size(0);
  System.out.println("检索条件:" + sourceBuilder.toString());
  searchRequest.source(sourceBuilder);
  // 执行
  SearchResponse searchResponse = client.search(searchRequest, LaketradingElasticsearchConfig.COMMON_OPTIONS);
  System.out.println(searchResponse.toString());
}

当然我们也可以在年龄聚合外来计算平均工资,也就是计算所有人的平均工资,那就把 balanceAvg 跟 ageAgg 同级即可。

代码语言:javascript
复制
AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age");
sourceBuilder.aggregation(ageAgg).aggregation(balanceAvg);

接下来我们要对命中记录进行分析,在官方文档中有一个 searchResponse.getHits() 方法。

文档位置:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-search.html

完整的代码测试

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class LaketradingSearchApplicationTests {

  @Autowired
  private RestHighLevelClient client;

  @Test
  public void search2Data() throws IOException {
    // 创建索引请求
    SearchRequest searchRequest = new SearchRequest();
    // 指定索引
    searchRequest.indices("bank");
    // 构造索引条件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
    // 聚合条件工具类
    AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
    TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age");
    sourceBuilder.aggregation(ageAgg).aggregation(balanceAvg);
    searchRequest.source(sourceBuilder);
    // 执行
    SearchResponse searchResponse = client.search(searchRequest, LaketradingElasticsearchConfig.COMMON_OPTIONS);
    // 获取命中结果
    SearchHit[] hits = searchResponse.getHits().getHits();
    for (SearchHit hit : hits) {
      // 拿到完整结果字符串
      String sourceAsString = hit.getSourceAsString();
      // 转换成实体类
      Source source = JSON.parseObject(sourceAsString, Source.class);
      System.out.println("source:" + source );
    }
    // 获取聚合结果
    Aggregations aggregations = searchResponse.getAggregations();
    Terms age = aggregations.get("ageAgg");
    age.getBuckets().forEach(bucket -> System.out.println("年龄: "+ bucket.getKeyAsString() + ",人数:" + bucket.getDocCount()));
    Avg balance = aggregations.get("balanceAvg");
    System.out.println("平均薪资:" + balance.getValue());
  }
}

@Data
@ToString
class Source {
  private int account_number;
  private int balance;
  private String firstname;
  private String lastname;
  private int age;
  private String gender;
  private String address;
  private String employer;
  private String email;
  private String city;
  private String state;
}

结果

代码语言:javascript
复制
source:Source(account_number=970, balance=19648, firstname=Forbes, lastname=Wallace, age=28, gender=M, address=990 Mill Road, employer=Pheast, email=forbeswallace@pheast.com, city=Lopezo, state=AK)
source:Source(account_number=136, balance=45801, firstname=Winnie, lastname=Holland, age=38, gender=M, address=198 Mill Lane, employer=Neteria, email=winnieholland@neteria.com, city=Urie, state=IL)
source:Source(account_number=345, balance=9812, firstname=Parker, lastname=Hines, age=38, gender=M, address=715 Mill Avenue, employer=Baluba, email=parkerhines@baluba.com, city=Blackgum, state=KY)
source:Source(account_number=472, balance=25571, firstname=Lee, lastname=Long, age=32, gender=F, address=288 Mill Street, employer=Comverges, email=leelong@comverges.com, city=Movico, state=MT)
年龄: 38,人数:2
年龄: 28,人数:1
年龄: 32,人数:1
平均薪资:25208.0

参考资料:松哥公众号


版权属于:乐心湖's Blog

本文链接:https://cloud.tencent.com/developer/article/1781409

声明:博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java操作方案
  • 举例测试
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档