SpringBoot3集成ElasticSearch

標簽:ElasticSearch8.Kibana8;

一、簡介

Elasticsearch是一個分布式、RESTful風格的搜索和數據分析引擎,適用于各種數據類型,數字、文本、地理位置、結構化數據、非結構化數據;

在實際的工作中,歷經過Elasticsearch從6.07.0的版本升級,而這次SpringBoot3和ES8.0的集成,雖然腳本的語法變化很小,但是Java客戶端的API語法變化很大;

二、環境搭建

1、下載安裝包

需要注意的是,這些安裝包的版本要選擇對應的,不然容易出問題;

軟件包:elasticsearch-8.8.2-darwin-x86_64.tar.gz
分詞器工具:elasticsearch-analysis-ik-8.8.2.zip
可視化工具:kibana-8.8.2-darwin-x86_64.tar.gz

2、服務啟動

不論是ES還是Kibana,在首次啟動后,會初始化很多配置文件,可以根據自己的需要做相關的配置調整,比如常見的端口調整,資源占用,安全校驗等;

1、啟動ES
elasticsearch-8.8.2/bin/elasticsearch本地訪問:localhost:92002、啟動Kibana
kibana-8.8.2/bin/kibana本地訪問:http://localhost:5601# 3、查看安裝的插件
http://localhost:9200/_cat/plugins  ->  analysis-ik 8.8.2

三、工程搭建

1、工程結構

2、依賴管理

starter-elasticsearch組件中,實際上依賴的是elasticsearch-java組件的8.7.1版本;

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId><version>${spring-boot.version}</version>
</dependency>

3、配置文件

在上面環境搭建的過程中,已經禁用了用戶和密碼的登錄驗證,配置ES服務地址即可;

spring:# ElasticSearch配置elasticsearch:uris: localhost:9200

四、基礎用法

1、實體類

通過DocumentField注解描述ES索引結構的實體類,注意這里JsonIgnoreProperties注解,解決索引中字段和實體類非一一對應的而引起的JSON解析問題;

@JsonIgnoreProperties(ignoreUnknown = true)
@Document(indexName = "contents_index", createIndex = false)
public class ContentsIndex implements Serializable {private static final long serialVersionUID=1L;@Field(type= FieldType.Integer)private Integer id;@Field(type= FieldType.Keyword)private String title;@Field(type= FieldType.Keyword)private String intro;@Field(type= FieldType.Text)private String content;@Field(type= FieldType.Integer)private Integer createId;@Field(type= FieldType.Keyword)private String createName;@Field(type= FieldType.Date,format = DateFormat.date_hour_minute_second)private Date createTime;
}

2、初始化索引

基于ElasticsearchTemplate類和上述實體類,實現索引結構的初始化,并且將tb_contents表中的數據同步到索引中,最后通過ID查詢一條測試數據;

@Service
public class ContentsIndexService {private static final Logger log = LoggerFactory.getLogger(ContentsIndexService.class);@Resourceprivate ContentsService contentsService ;@Resourceprivate ElasticsearchTemplate template ;/*** 初始化索引結構和數據*/public void initIndex (){// 處理索引結構IndexOperations indexOps = template.indexOps(ContentsIndex.class);if (indexOps.exists()){boolean delFlag = indexOps.delete();log.info("contents_index exists,delete:{}",delFlag);indexOps.createMapping(ContentsIndex.class);} else {log.info("contents_index not exists");indexOps.createMapping(ContentsIndex.class);}// 同步數據庫表記錄List<Contents> contentsList = contentsService.queryAll();if (contentsList.size() > 0){List<ContentsIndex> contentsIndexList = new ArrayList<>() ;contentsList.forEach(contents -> {ContentsIndex contentsIndex = new ContentsIndex() ;BeanUtils.copyProperties(contents,contentsIndex);contentsIndexList.add(contentsIndex);});template.save(contentsIndexList);}// ID查詢ContentsIndex contentsIndex = template.get("10",ContentsIndex.class);log.info("contents-index-10:{}",contentsIndex);}
}

3、倉儲接口

繼承ElasticsearchRepository接口,可以對ES這種特定類型的存儲庫進行通用增刪改查操作;在測試類中對該接口的方法進行測試;

// 1、接口定義
public interface ContentsIndexRepository extends ElasticsearchRepository<ContentsIndex,Long> {
}// 2、接口測試
public class ContentsIndexRepositoryTest {@Autowiredprivate ContentsIndexRepository contentsIndexRepository;@Testpublic void testAdd (){// 單個新增contentsIndexRepository.save(buildOne());// 批量新增contentsIndexRepository.saveAll(buildList()) ;}@Testpublic void testUpdate (){// 根據ID查詢后再更新Optional<ContentsIndex> contentsOpt = contentsIndexRepository.findById(14L);if (contentsOpt.isPresent()){ContentsIndex contentsId = contentsOpt.get();System.out.println("id=14:"+contentsId);contentsId.setContent("update-content");contentsId.setCreateTime(new Date());contentsIndexRepository.save(contentsId);}}@Testpublic void testQuery (){// 單個ID查詢Optional<ContentsIndex> contentsOpt = contentsIndexRepository.findById(1L);if (contentsOpt.isPresent()){ContentsIndex contentsId1 = contentsOpt.get();System.out.println("id=1:"+contentsId1);}// 批量ID查詢Iterator<ContentsIndex> contentsIterator = contentsIndexRepository.findAllById(Arrays.asList(10L,12L)).iterator();while (contentsIterator.hasNext()){ContentsIndex contentsIndex = contentsIterator.next();System.out.println("id="+contentsIndex.getId()+":"+contentsIndex);}}@Testpublic void testDelete (){contentsIndexRepository.deleteById(15L);contentsIndexRepository.deleteById(16L);}
}

4、查詢語法

無論是ElasticsearchTemplate類還是ElasticsearchRepository接口,都是對ES常用的簡單功能進行封裝,在實際使用時,復雜的查詢語法還是依賴ElasticsearchClient和原生的API封裝;

這里主要演示七個查詢方法,主要涉及:ID查詢,字段匹配,組合與范圍查詢,分頁與排序,分組統計,最大值查詢和模糊匹配;更多的查詢API還是要多看文檔中的案例才行;

public class ElasticsearchClientTest {@Autowiredprivate ElasticsearchClient client ;@Testpublic void testSearch1 () throws IOException {// ID查詢GetResponse<ContentsIndex> resp = client.get(getReq ->getReq.index("contents_index").id("7"), ContentsIndex.class);if (resp.found()){ContentsIndex contentsIndex = resp.source() ;System.out.println("contentsIndex-7:"+contentsIndex);}}@Testpublic void testSearch2 () throws IOException {// 指定字段匹配SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").query(query -> query.match(field -> field.field("createName").query("張三"))),ContentsIndex.class);printResp(resp);}@Testpublic void testSearch3 () throws IOException {// 組合查詢:姓名和時間范圍Query byName = MatchQuery.of(field -> field.field("createName").query("王五"))._toQuery();Query byTime = RangeQuery.of(field -> field.field("createTime").gte(JsonData.of("2023-07-10T00:00:00")).lte(JsonData.of("2023-07-12T00:00:00")))._toQuery();SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").query(query -> query.bool(boolQuery -> boolQuery.must(byName).must(byTime))),ContentsIndex.class);printResp(resp);}@Testpublic void testSearch4 () throws IOException {// 排序和分頁,在14條數據中,根據ID倒序排列,從第5條往后取4條數據SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").from(5).size(4).sort(sort -> sort.field(sortField -> sortField.field("id").order(SortOrder.Desc))),ContentsIndex.class);printResp(resp);}@Testpublic void testSearch5 () throws IOException {// 根據createId分組統計SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").aggregations("createIdGroup",agg -> agg.terms(term -> term.field("createId"))),ContentsIndex.class);Aggregate aggregate = resp.aggregations().get("createIdGroup");LongTermsAggregate termsAggregate = aggregate.lterms();Buckets<LongTermsBucket> buckets = termsAggregate.buckets();for (LongTermsBucket termsBucket : buckets.array()) {System.out.println(termsBucket.key() + " : " + termsBucket.docCount());}}@Testpublic void testSearch6 () throws IOException {// 查詢最大的IDSearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").aggregations("maxId",agg -> agg.max(field -> field.field("id"))),ContentsIndex.class);for (Map.Entry<String, Aggregate> entry : resp.aggregations().entrySet()){System.out.println(entry.getKey()+":"+entry.getValue().max().value());}}@Testpublic void testSearch7 () throws IOException {// 模糊查詢title字段,允許1個誤差Query byContent = FuzzyQuery.of(field -> field.field("title").value("設計").fuzziness("1"))._toQuery();SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").query(byContent),ContentsIndex.class);printResp(resp);}private void printResp (SearchResponse<ContentsIndex> resp){TotalHits total = resp.hits().total();System.out.println("total:"+total);List<Hit<ContentsIndex>> hits = resp.hits().hits();for (Hit<ContentsIndex> hit: hits) {ContentsIndex contentsIndex = hit.source();System.out.println(hit.id()+":"+contentsIndex);}}
}

五、參考源碼

文檔倉庫:
https://gitee.com/cicadasmile/butte-java-note源碼倉庫:
https://gitee.com/cicadasmile/butte-spring-parent

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42814.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42814.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42814.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

南大通用數據庫(gbase 8s) 在Centos7環境 集群安裝

國產數據庫-達夢 一、環境詳情二、Centos7 參數優化&#xff08;所有節點&#xff09;三、創建gbase用戶&#xff08;所有節點&#xff09;四、 安裝部署&#xff0c;只在node1 安裝即可同步五、數據庫卸載六、數據庫連接與使用 當前安裝 在指定版本環境下 測試&#xff0c;僅供…

QT的設計器介紹

設計器介紹 Qt制作 UI 界面&#xff0c;一般可以通過UI制作工具QtDesigner和純代碼編寫兩種方式來實現。純代碼實現暫時在這里不闡述了在后續布局章節詳細說明&#xff0c;QtDesigner已經繼承到開發環境中&#xff0c;在工程中直接雙擊ui文件就可以直接在QtDesigner設計器中打…

【100天精通python】Day39:GUI界面編程_PyQt 從入門到實戰(下)_圖形繪制和動畫效果,數據可視化,刷新交互

目錄 專欄導讀 6 圖形繪制與動畫效果 6.1 繪制基本圖形、文本和圖片 6.2 實現動畫效果和過渡效果 7 數據可視化 7.1 使用 Matplotlib繪制圖表 7.2 使用PyQtGraph繪制圖表 7.3 數據的實時刷新和交互操作 7.3.1 數據的實時刷新 7.3.2 交互操作 7.4 自定義數據可視化…

C# 窗體永遠在最前

C# 窗體永遠在最前 1、調用系統API public const int HWND_TOP 0;public const int HWND_BOTTOM 1;public const int HWND_TOPMOST -1;public const int HWND_NOTOPMOST -2;//設置此窗體為活動窗體&#xff1a;//將創建指定窗口的線程帶到前臺并激活該窗口。鍵盤輸入直接指…

【WPF】 本地化的最佳做法

【WPF】 本地化的最佳做法 資源文件英文資源文件 en-US.xaml中文資源文件 zh-CN.xaml 資源使用App.xaml主界面布局cs代碼 App.config輔助類語言切換操作類資源 binding 解析類 實現效果 應用程序本地化有很多種方式&#xff0c;選擇合適的才是最好的。這里只討論一種方式&#…

Unity制作一個簡單的登入注冊頁面

1.創建Canvas組件 首先我們創建一個Canvas畫布&#xff0c;我們再在Canvas畫布底下創建一個空物體&#xff0c;取名為Resgister。把空物體的錨點設置為全屏撐開。 2.我們在Resgister空物體底下創建一個Image組件&#xff0c;改名為bg。我們也把它 的錨點設置為全屏撐開狀態。接…

【深入理解ES6】字符串和正則表達式

概念 字符串&#xff08;String&#xff09;是JavaScript6大原始數據類型。其他幾個分別是Boolean、Null、Undefined、Number、Symbol&#xff08;es6新增&#xff09;。 更好的Unicode支持 1. UTF-16碼位 字符串里的字符有兩種&#xff1a; 前 個碼位均以16位的編碼單元…

每日一道面試題之session 和 cookie 有什么區別?

Session和Cookie是兩種在Web開發中用于跟蹤用戶狀態的機制&#xff1a; 它們之間的區別如下&#xff1a; 存儲位置&#xff1a;Cookie是存儲在用戶瀏覽器中的小型文本文件&#xff0c;而Session是存儲在服務器上的數據結構。 數據安全性&#xff1a;Cookie中的數據可以被用戶…

總結,由于順豐的問題,產生了電腦近期一個月死機問題集錦

由于我搬家&#xff0c;我媽搞順豐發回家&#xff0c;但是沒有檢查有沒有壞&#xff0c;并且我自己由于不可抗力因素&#xff0c;超過了索賠時間&#xff0c;反饋給順豐客服&#xff0c;說超過了造成了無法索賠的情況&#xff0c;現在總結發生了損壞配件有幾件&#xff0c;顯卡…

NLP | 論文摘要文本分類

基于論文摘要的文本分類與關鍵詞抽取挑戰賽??????2023 iFLYTEK A.I.開發者大賽-訊飛開放平臺 環境需求&#xff1a;Anaconda-JupyterNotebook&#xff0c;或者百度AIStudio 賽題解析&#xff1a; 【文本二分類任務】根據論文摘要等信息理解&#xff0c;將論文劃分為0-1兩…

文心一言最新重磅發布!

8月16日&#xff0c;由深度學習技術及應用國家工程研究中心主辦的WAVE SUMMIT深度學習開發者大會2023舉辦。百度首席技術官、深度學習技術及應用國家工程研究中心主任王海峰以《大語言模型為通用人工智能帶來曙光》為題&#xff0c;闡述了大語言模型具備理解、生成、邏輯、記憶…

【云原生】k8s存儲管理中ConfigMap Secret的使用

目錄 1 ConfigMap 1.1 簡介 1.2 優點 1.3 定義 ConfigMap 1.4 使用 2 Secret 2.1 簡介 2.1 定義 Secret 2.2 使用 1 ConfigMap 1.1 簡介 在 Kubernetes 中&#xff0c;ConfigMap 是一種用于存儲非敏感信息的 Kubernetes 對象。它用于存儲配置數據&#xff0c;如鍵值…

樹莓派系統入門教程(三)—— 使用Windows上的VSCode遠程連接樹莓派進行Python開發

樹莓派系統入門教程&#xff08;三&#xff09;—— 使用Windows上的VSCode遠程連接樹莓派進行Python開發 1. 安裝VSCode和SSH擴展2. SSH連接配置3. 連接到樹莓派4. 運行Python程序5. 建議和注意事項 很多開發者更喜歡在大屏幕和強大的開發環境中編寫代碼&#xff0c;但同時他們…

Vue 2 動態組件和異步組件

先閱讀 【Vue 2 組件基礎】中的初步了解動態組件。 動態組件與keep-alive 我們知道動態組件使用is屬性和component標簽結合來切換不同組件。 下面給出一個示例&#xff1a; <!DOCTYPE html> <html><head><title>Vue 動態組件</title><scri…

Typora 相對路徑保存圖片以及 Gitee 無法顯示圖片

目錄 Typora 相對路徑保存圖片 Gitee 無法顯示圖片 Typora 相對路徑保存圖片 Step1&#xff1a;修改 Typora 的偏好設置 自動在當前目錄創建名為 "./${filename}.assets" 的文件夾粘貼圖片到 md 中時&#xff0c;圖片會自動另存到 "./${filename}.assets&qu…

iptables學習筆記

iptables的結構&#xff1a; iptables由上而下&#xff0c;由Tables&#xff0c;Chains&#xff0c;Rules組成。 一、iptables的表tables與鏈chains iptables有Filter, NAT, Mangle, Raw四種內建表&#xff1a; 1. Filter表 Filter是iptables的默認表&#xff0c;它有以下…

LVGL基本控件介紹

1. 弧(lv_arc) 特點 弧的0度在右邊&#xff0c;90度在下邊 效果圖 源碼 void lv_arc_demo(void) {/* Create an Arc */lv_obj_t* arc lv_arc_create(lv_scr_act(), NULL);/* Set Background range */lv_arc_set_bg_angles(arc, 0, 360);/* Set Forward range */lv_arc_set…

第十課:Qt 字符編碼和中文亂碼相關問題

功能描述&#xff1a;最全的 Qt 字符編碼相關知識以及中文亂碼的原因與解決辦法 一、字符編碼種類 ASCII 碼 美國人對信息交流的編碼&#xff0c;包括 26 個字母&#xff08;大小寫&#xff09;、數字和標點符號等&#xff0c;用一個字節&#xff08;8 位&#xff09;表示這些…

eNSP:VLAN-hybrid實驗應用

實驗要求&#xff1a; 拓撲圖 配置 sw1: [sw1]vlan batch 2 to 6[sw1]int Ethernet 0/0/2 [sw1-Ethernet0/0/2]port link-type access [sw1-Ethernet0/0/2]port default vlan 2 [sw1-Ethernet0/0/2]int e 0/0/4 [sw1-Ethernet0/0/4]port link-ty access [sw1-Ethernet0/0/…