天天看點

接上篇:如何在項目中實作ES查詢功能?

作者:王路飛學Java

大家好,之前我們教大家如何将 MySQL 資料同步到 ES。

這篇文章在技術派項目中實作 ES 查詢功能。

不多說上文章目錄:

接上篇:如何在項目中實作ES查詢功能?

01 背景

在 SpringBoot 整合 ES 中,有兩種常見方法,一種是 ElasticsearchRestTemplate,另一種是 RestHighLevelClient。

ElasticsearchRestTemplate 是 ES 基于 Spring 內建用法,但是用法比較單一,有些複雜查詢無法完成;另一種 RestHighLevelClient 是 ES 原生用戶端,适合各種場景查詢。

綜合考慮下來技術派采用後者 ES 原生用戶端 RestHighLevelClient。

02 構造用戶端

2.1 引入依賴

在 paicoding-service 子產品中的 pom 檔案中引入 es 和 es-client 相關依賴。

<!--引入es-high-level-client相關依賴  start-->
<dependency>
  <groupId>org.elasticsearch</groupId>
  <artifactId>elasticsearch</artifactId>
  <version>6.8.2</version>
</dependency>

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

2.2 配置檔案

在 paicoding-web 子產品中 src->main->resource-env->dev->application-dal.yml 中配置 ES 相關配置,配置如下所示:

# elasticsearch配置
elasticsearch:
  # 是否開啟ES?本地啟動如果沒有安裝ES,可以設定為false關閉ES
  open: true
  # es叢集名稱
  clusterName: elasticsearch
  hosts: 127.0.0.1:9200
  userName: elastic
  password: elastic
  # es 請求方式
  scheme: http
  # es 連接配接逾時時間
  connectTimeOut: 1000
  # es socket 連接配接逾時時間
  socketTimeOut: 30000
  # es 請求逾時時間
  connectionRequestTimeOut: 500
  # es 最大連接配接數
  maxConnectNum: 100
  # es 每個路由的最大連接配接數
  maxConnectNumPerRoute: 100
           

注意 yml 格式,千萬别出錯。

接上篇:如何在項目中實作ES查詢功能?

配置的具體介紹我就不再重複介紹了,在 yml 的注解中已經詳細的标注了,請小夥伴們詳細看看哦。

2.3 配置類

配置類其實也就是交由 Spring 去建立 RestHighLevelClient 用戶端,配置類代碼如下所示:

package com.github.paicoding.forum.service.config.es;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * es配置類
 *
 * @author ygl
 * @since 2023-05-25
 **/
@Slf4j
@Data
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticsearchConfig {

    // 是否開啟ES
    private Boolean open;

    // es host ip 位址(叢集)
    private String hosts;

    // es使用者名
    private String userName;

    // es密碼
    private String password;

    // es 請求方式
    private String scheme;

    // es叢集名稱
    private String clusterName;

    // es 連接配接逾時時間
    private int connectTimeOut;

    // es socket 連接配接逾時時間
    private int socketTimeOut;

    // es 請求逾時時間
    private int connectionRequestTimeOut;

    // es 最大連接配接數
    private int maxConnectNum;

    // es 每個路由的最大連接配接數
    private int maxConnectNumPerRoute;


    /**
     * 如果@Bean沒有指定bean的名稱,那麼這個bean的名稱就是方法名
     */
    @Bean(name = "restHighLevelClient")
    public RestHighLevelClient restHighLevelClient() {

        // 此處為單節點es
        String host = hosts.split(":")[0];
        String port = hosts.split(":")[1];
        HttpHost httpHost = new HttpHost(host, Integer.parseInt(port));

        // 建構連接配接對象
        RestClientBuilder builder = RestClient.builder(httpHost);

        // 設定使用者名、密碼
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));

        // 連接配接延時配置
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(connectTimeOut);
            requestConfigBuilder.setSocketTimeout(socketTimeOut);
            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
            return requestConfigBuilder;
        });
        // 連接配接數配置
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(maxConnectNum);
            httpClientBuilder.setMaxConnPerRoute(maxConnectNumPerRoute);
            httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            return httpClientBuilder;
        });

        return new RestHighLevelClient(builder);
    }
}
           

其實配置類中也就是構造 RestHighLevelClient 用戶端。注意是放在 paicoding-service 子產品中。

接上篇:如何在項目中實作ES查詢功能?

注意:在 yml 中的 elasticsearch.hosts 中千萬不要加 https 字首,隻需要 127.0.0.1:9200 即可(我在這裡翻車過);否則在配置類中 new HttpHost() 會出錯。

03 查詢 ES

在整合之前我先來說下大緻邏輯:

  • 根據查詢條件去ES中查詢出資料;
  • 從查詢出所有資料中取出 id,然後将 id 去 add 進 ids 中;
  • 拿到 ids 後去 MySQL 資料庫中撈資料。

這一套流程下來,要比根據查詢條件進行 like% 值 % 不走索引查詢效率性能好的多。

然後開始編寫實作代碼,代碼實作及過程如下所示:

接上篇:如何在項目中實作ES查詢功能?

04 相容 MySQL

考慮到有的小夥伴沒有安裝 ES 和 Canal,為了讓代碼能夠查詢首頁時還是走 MySQL 資料庫,我這邊特意做了相容,即使沒有安裝 ES 等也是可以正常運作。

首先我在 yml 中增加了是否開啟 ES 值。

接上篇:如何在項目中實作ES查詢功能?

然後在 Service 層将 open 值注入。

接上篇:如何在項目中實作ES查詢功能?

最後在代碼層面業務層實作。

接上篇:如何在項目中實作ES查詢功能?

05 代碼倉庫

為了友善大家學習功能演變的過程,每個子產品都會單獨開個分支,代碼分支、代碼 Diff 如下:

  • 代碼分支:feature/mysql_es_20230523
  • 代碼 Diff:https://github.com/itwanger/paicoding/pull/51/files

建議大家先看代碼 Diff,這樣你就知道所有的改動,非常便于自己學習。

接上篇:如何在項目中實作ES查詢功能?

06 總結

我們再回顧一下整體執行流程:

接上篇:如何在項目中實作ES查詢功能?

寫到這裡,就結束了,是不是滿滿的幹貨呢?這兩篇文章,從原理到實踐,手把手教你如何将 MySQL 同步到 ES,并應用到實際場景中,如果你的項目也需要用到該場景,基本可以直接照搬。

原文:https://mp.weixin.qq.com/s/WVGacMS9xqrNY1_ko1aP3Q

作者:樓仔

如果感覺本文對你有幫助,點贊關注支援一下

繼續閱讀