大家好,之前我們教大家如何将 MySQL 資料同步到 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 格式,千萬别出錯。
配置的具體介紹我就不再重複介紹了,在 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 子產品中。
注意:在 yml 中的 elasticsearch.hosts 中千萬不要加 https 字首,隻需要 127.0.0.1:9200 即可(我在這裡翻車過);否則在配置類中 new HttpHost() 會出錯。
03 查詢 ES
在整合之前我先來說下大緻邏輯:
- 根據查詢條件去ES中查詢出資料;
- 從查詢出所有資料中取出 id,然後将 id 去 add 進 ids 中;
- 拿到 ids 後去 MySQL 資料庫中撈資料。
這一套流程下來,要比根據查詢條件進行 like% 值 % 不走索引查詢效率性能好的多。
然後開始編寫實作代碼,代碼實作及過程如下所示:
04 相容 MySQL
考慮到有的小夥伴沒有安裝 ES 和 Canal,為了讓代碼能夠查詢首頁時還是走 MySQL 資料庫,我這邊特意做了相容,即使沒有安裝 ES 等也是可以正常運作。
首先我在 yml 中增加了是否開啟 ES 值。
然後在 Service 層将 open 值注入。
最後在代碼層面業務層實作。
05 代碼倉庫
為了友善大家學習功能演變的過程,每個子產品都會單獨開個分支,代碼分支、代碼 Diff 如下:
- 代碼分支:feature/mysql_es_20230523
- 代碼 Diff:https://github.com/itwanger/paicoding/pull/51/files
建議大家先看代碼 Diff,這樣你就知道所有的改動,非常便于自己學習。
06 總結
我們再回顧一下整體執行流程:
寫到這裡,就結束了,是不是滿滿的幹貨呢?這兩篇文章,從原理到實踐,手把手教你如何将 MySQL 同步到 ES,并應用到實際場景中,如果你的項目也需要用到該場景,基本可以直接照搬。
原文:https://mp.weixin.qq.com/s/WVGacMS9xqrNY1_ko1aP3Q
作者:樓仔
如果感覺本文對你有幫助,點贊關注支援一下