【ElasticSearch(十三)进阶】SpringBoot整合ElasticSearch7.14.0 基本教程

【ElasticSearch(十三)进阶】SpringBoot整合ElasticSearch7.14.0 基本教程

一、接入方式

1.端口9300:TCP

1)spring-data-elasticsearch:transport-api.jar:

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

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


2.端口9200:HTTP

1)JestClient

非官方,更新慢

2)RestTemplate

模拟发HTTP请求,ES很多操作需要自己封装,麻烦

3)HttpClient

同上

4)Elasticsearch-Rest-Client(我们选择的)

官方RestClient,封装了ES操作,API层次分明,上手简单


(使用指南)

https://www.elastic.co/guide/en/elasticsearch/client/index.html



二、搭建项目

我使用的版本是ElasticSearch 7.14,配合SpringBoot搭建项目。




三、导入Maven

由于父依赖spring-boot-dependencies导入的elasticsearch依赖版本是7.12.1的,所以这里我们另外在<properties>标签下定义下elasticsearch版本是7.14的。

<properties>
    <java.version>1.8</java.version>
    <elasticsearch.version>7.14.0</elasticsearch.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!-- 导入es的rest-high-level-client和elasticsearch server-->
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.14.0</version>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>7.14.0</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

四、建立Config

建立config文件夹,创建类ElasticSearchConfig ,作为我们的配置文件。

给容器中注入一个RestHighLevelClient

package com.musecho.gulimallsearch.config;

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

@Configuration
public class ElasticSearchConfig {

    /**
     * 创建单例模式的RequestOptions,使得所有请求共用
     */
    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 client() {
        RestClientBuilder builder=RestClient.builder(new HttpHost("localhost", 9200, "http"));
        RestHighLevelClient client = new RestHighLevelClient(builder);
        return client;
    }
}

五、测试:保存数据

保存一个user信息,使用index()

package com.musecho.gulimallsearch;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.musecho.gulimallsearch.config.ElasticSearchConfig;
import com.musecho.gulimallsearch.pojo.User;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;

@SpringBootTest
public class GulimallSearchApplicationTests {

    @Autowired
    private RestHighLevelClient client;

    /**
     * jackson的objectMapper
     */
    ObjectMapper objectMapper=new ObjectMapper();

    /**
     * 测试RestHighLevelClient注入是否成功
     */
    @Test
    public void contextLoads() {
        System.out.println(client);
    }

    /**
     * 保存用户数据
     */
    @Test
    public void indexData() throws IOException {
        //指定索引和id
        IndexRequest request=new IndexRequest("users");
        request.id("1");

        //数据转为json格式
        User user=new User("zhengkeke","女",9);
        String userString=objectMapper.writeValueAsString(user);
        request.source(userString, XContentType.JSON);

        //执行保存操作
        IndexResponse indexResponse=client.index(request, ElasticSearchConfig.COMMON_OPTIONS);

        System.out.println(indexResponse);
    }

}

通过Kinaba查询是否添加成功:

GET /users/_search

返回结果如下, 保存数据成功

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "zhengkeke",
          "sex" : "女",
          "age" : 9
        }
      }
    ]
  }
}

六、测试:复杂检索数据

现在用java结合ES实现这个查询

#搜索 address中包含mill的所有人的年龄分布以及平均年龄
GET /bank/_search
{
  "query":{
    "match":{
      "address":"mill"
    }
  },
  "aggs":{
    "ageAgg":{
      "terms":{
        "field": "age",
        "size": 10
      }
    },
    "ageAvg":{
      "avg":{
        "field":"age"
      }
    }
  }
}

类GulimallSearchApplicationTests中添加方法searchData()

/**
     * 复杂检索数据
     */
@Test
public void searchData() throws IOException {
    //1.创建检索请求
    SearchRequest searchRequest = new SearchRequest();
    //指定索引
    searchRequest.indices("bank");
    //指定DSL,检索条件
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

    //1.1 构造检索条件
    //address中包含mill
    searchSourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
    //按照前10种年龄分布进行聚合
    TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
    searchSourceBuilder.aggregation(ageAgg);
    //求所有人年龄的平均值
    AvgAggregationBuilder ageAvg = AggregationBuilders.avg("ageAvg").field("age");
    searchSourceBuilder.aggregation(ageAvg);

    System.out.println(searchSourceBuilder);
    searchRequest.source(searchSourceBuilder);


    //2.执行检索
    SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);

    //3.分析结果
    //3.1 查看查询结果
    SearchHits hits = searchResponse.getHits();
    SearchHit[] searchHits = hits.getHits();
    for (SearchHit hit : searchHits) {
        System.out.println(hit);
    }
    //3.2 查看聚合结果
    Aggregations aggs = searchResponse.getAggregations();

    Terms ageAgg2 = aggs.get("ageAgg");
    for (Terms.Bucket bucket : ageAgg2.getBuckets()) {
        System.out.println("年龄:" + bucket.getKeyAsString()+"==> 人数:"+bucket.getDocCount());
    }
    System.out.println();

    Avg ageAvg2 = aggs.get("ageAvg");
    System.out.println("平均年龄:" + ageAvg2.getValue());
}

控制台打印结果:

//请求条件
{
    "query": {
        "match": {
            "address": {
                "query": "mill", 
                "operator": "OR", 
                "prefix_length": 0, 
                "max_expansions": 50, 
                "fuzzy_transpositions": true, 
                "lenient": false, 
                "zero_terms_query": "NONE", 
                "auto_generate_synonyms_phrase_query": true, 
                "boost": 1
            }
        }
    }, 
    "aggregations": {
        "ageAgg": {
            "terms": {
                "field": "age", 
                "size": 10, 
                "min_doc_count": 1, 
                "shard_min_doc_count": 0, 
                "show_term_doc_count_error": false, 
                "order": [
                    {
                        "_count": "desc"
                    }, 
                    {
                        "_key": "asc"
                    }
                ]
            }
        }, 
        "ageAvg": {
            "avg": {
                "field": "age"
            }
        }
    }
}

//查询结果
{
    "_index" : "bank",
    "_type" : "account",
    "_id" : "970",
    "_score" : 5.4032025,
    "_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"
    }
}
{
    "_index" : "bank",
    "_type" : "account",
    "_id" : "136",
    "_score" : 5.4032025,
    "_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"
    }
}
{
    "_index" : "bank",
    "_type" : "account",
    "_id" : "345",
    "_score" : 5.4032025,
    "_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"
    }
}
{
    "_index" : "bank",
    "_type" : "account",
    "_id" : "472",
    "_score" : 5.4032025,
    "_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

平均年龄:34.0
posted @ 2021-08-24 13:54  musecho  阅读(1380)  评论(0编辑  收藏  举报