8. ElasticSearch——整合SpringBoot

1. 前言       

1.1 java发送es通常有两种方式

1.1.1 通过9300 TCP端口

要通过9300发送es,就需要与es建立一个长连接,该操作,在有api与之对应:spring-data-elasticsearch:transport-api.jar,但是我们在java中一般不会通过该端口操作,原因如下

1) springboot版本不同,transport-api.jar不同,不能适配es版本

2) 7.X已经不建议使用,8以后就要废弃

3) ES集群节点之间的通信也是使用的9300端口

1.1.2 通过9200 HTTP端口

通过HTTP端口发送请求,方式很多

1) JestClient:非官方,更新慢

2) RestTemplate:模拟HTTP请求,ES很多操作需要自己封装,麻烦

3) HTTPClient:同上

4)Elasticsearch-Rest-Client:官方RestClient,封装了ES操作,API层次分明,上手简单

官网(https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-api.html)截图,如下

所以,最终选择 Elasticsearch-Rest-Client(elasticsearch-rest-high-level-client)

查看官网(https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-maven.html),可以看到依赖如下

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

2. 整合SpringBoot

2.1 新建项目

2.2 添加 Java High Level REST Client依赖

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

如图:

发现ElasticSearch的版本是6.4.3,这是因为boot对elasticsearch进行了管理,如图:

所以,这里我们需要改变版本号

<elasticsearch.version>7.4.2</elasticsearch.version>

再次查看版本依赖,如图;

2.3 配置

2.3.1 注册中心配置

1)配置文件

application.yml

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: gulimall-search

2)开启服务发现与注册

2.3.2 配置es,给容器注册RestHighLevelClient

1)导入依赖(已完成)

2)配置类

查看官网,如图;

所以,配置类如下:

package com.bjc.gulimall.search.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GulimallElasticSearchConfig {

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

2.3.3 测试

package com.bjc.gulimall.search;

import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
class GulimallSearchApplicationTests {

    @Autowired
    private RestHighLevelClient client;

    @Test
    void test01() {
        System.out.println(client);
    }

}

测试结果:

可以打印出对象,说明可以操作client对象了。之后就可以根据官方API来进行操作es了。

3. API的使用

打开Java High Level REST Client的api界面(https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high.html),从Getting started 开始,如图:

3.1 请求设置项RequestOptions

RequestOptions用于对所有的请求进行统一的请求头设置。

参看官网,如图:

将该段代码配置到项目中

@Configuration
public class GulimallElasticSearchConfig {

    /* 通用设置项,基于默认规则 */
    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(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));
        return client;
    }
}

3.2 存储Index Api

3.2.1 存储方式

3.2.1.1 通过json字符串存储

操作步骤:

1)创建IndexRequest对象并指定post请求类型

2)设置数据id

3)获取数据的json串

4)发送请求

如图:

3.2.1.2 通过map实现

如图:

3.2.1.3 使用XContentBuilder 构造器

XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
    builder.field("user", "kimchy");
    builder.timeField("postDate", new Date());
    builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("posts")
    .id("1").source(builder);  

3.2.1.4 直接利用source的键值对方式

IndexRequest indexRequest = new IndexRequest("posts")
    .id("1")
    .source("user", "kimchy",
        "postDate", new Date(),
        "message", "trying out Elasticsearch"); 

3.2.2 其他设置

1)设置超时时间

request.timeout(TimeValue.timeValueSeconds(1)); 
request.timeout("1s");

2)设置等待刷新策略

request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 
request.setRefreshPolicy("wait_for");  

3)设置版本号

request.version(2); 

4)设置管道

request.setPipeline("pipeline"); 

3.2.3 执行Index

3.3.1 同步执行

IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

3.2.3 异步执行

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

异步执行会有一个监听器,可以理解为js中的回调函数

listener = new ActionListener<IndexResponse>() {
    @Override
    public void onResponse(IndexResponse indexResponse) {
        
    }

    @Override
    public void onFailure(Exception e) {
        
    }
};

3.2.4 保存测试

@RunWith(SpringRunner.class)
@SpringBootTest
class GulimallSearchApplicationTests {

    @Autowired
    private RestHighLevelClient client;

    @Test
    public void indexTest() throws IOException {
        // users 索引名称
        IndexRequest request = new IndexRequest("users");
        request.id("1");    // 设置数据id  如果不指定id值,就默认自增
        // 组装要保存的数据
        Map<String,String> map = new HashMap<>();
        map.put("name","张三");
        map.put("age","18");
        map.put("gender","F");
        map.put("addr","中国");

        // 要保存的内容并指定内容类型
        request.source(JSONObject.toJSONString(map), XContentType.JSON);
        // 使用客户端执行索引保存
        IndexResponse indexResponse = client.index(request, GulimallElasticSearchConfig.COMMON_OPTIONS);

        // 提取响应信息
        System.out.println(indexResponse);
    }

}

打印结果:

在kibana查询,结果如图

3.3 检索数据

3.3.1 简单的GET检索

参看官网APIhttps://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high-document-get.html

根据id检索

@Autowired
private RestHighLevelClient client;

@Test
public void getTest() throws IOException {
     // 参数一:索引名
     // 参数二:id
    GetRequest request = new GetRequest("users","1");
    GetResponse getResponse = client.get(request, GulimallElasticSearchConfig.COMMON_OPTIONS);
    System.out.println(getResponse);
}

 

3.4 Search API检索

参看官网:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high-search.html 

参看官网实例,可以知道要做检索,需要构建一个检索请求SearchRequest

例如:

@Autowired
private RestHighLevelClient client;

@Test
public void conditionTest() throws IOException {
    // 1. 构建检索请求
    SearchRequest searchRequest = new SearchRequest();
    // 2. 指定检索索引
    searchRequest.indices("bank");

    // 3.1 指定DSL内容
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    // 3.1.1 构建query条件
    searchSourceBuilder.query(QueryBuilders.matchQuery("address","mill"));  // 匹配address包含mill的雇员
    // 3.1.2 构建聚合条件
    // 按照age的值分布聚合,并给该次统计取一个名字aggAge
    TermsAggregationBuilder aggAge = AggregationBuilders.terms("aggAge").field("age").size(10);
    searchSourceBuilder.aggregation(aggAge);
    // 计算平均薪资
    AvgAggregationBuilder banlanceAvg = AggregationBuilders.avg("banlanceAvg").field("balance");
    searchSourceBuilder.aggregation(banlanceAvg);

    // 3. 创建检索条件 用于构建DSL语言
    searchRequest.source(searchSourceBuilder);

    // 4. 执行检索
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

    // 5. 分析结果
    // 5.1 获取所有查到的记录
    SearchHits hits = searchResponse.getHits();
    // 5.2 获取所有命中的记录
    SearchHit[] searchHits = hits.getHits();
    for (SearchHit hit : searchHits) {
        System.out.println(hit.getId());
        System.out.println(hit.getSourceAsMap());
    }

    // 5.3 获取分析(聚合)信息
    Aggregations aggregations = searchResponse.getAggregations();
    Terms terms = aggregations.get("aggAge");
    terms.getBuckets().forEach(item -> System.out.println("年龄:"+ item.getKeyAsString() + "  total:" + item.getDocCount()));

    Avg blanceAvg = aggregations.get("banlanceAvg");
    System.out.println("平均薪资:" + blanceAvg.getValue());
}

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值