SpringBoot集成ES實現存儲、查詢

  • 2019 年 10 月 5 日
  • 筆記

5分鐘_SpringBoot集成ES實現存儲、查詢

當前文章使用ES版本為6.4.3, SpringBoot版本為:2.1.8.RELEASE spring-boot-starter-data-elasticsearch版本為:2.1.8.RELEASE

spring-boot-starter-data-elasticsearch介紹

spring-boot-starter-data-elasticsearch:是springboot整合es的一個快速開發包。用過JPA的朋友應該知道,springdata是通過解析方法名來實現查詢資料庫的。同樣的這個快速開發包也是大大簡化了Java使用es的流程。

ik分詞器

IKAnalyzer是一個開源的,基於java語言開發的輕量級的中文分詞工具包。也可以引入其他的中文分詞器,本文使用IK分詞器,注意:IK分詞器的版本號,要與ES的版本一致,如不一致則無法啟動。如果不引入中文分詞器,那麼ES會默認將每一個中文都會進行分詞,不會智慧組詞。

下載地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

源程式碼:https://github.com/medcl/elasticsearch-analysis-ik

搭建springBoot工程

導入依賴

可以在創建工程時候進行選擇web、ES的依賴,也可以手動進行添加。

  • 創建工程時候勾選
  • 手動添加
<dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-data-elasticsearch</artifactId>          </dependency>          <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-web</artifactId>          </dependency>            <!--          可以只添加上方兩個依賴即可            推薦添加下方依賴,可以簡化程式碼,不需要在實體類中書寫getter和setter方法。如果idea/eclipse報錯,請安裝lombok插件。          -->            <dependency>              <groupId>org.projectlombok</groupId>              <artifactId>lombok</artifactId>              <optional>true</optional>          </dependency>

編寫配置

application.yml

主要配置ES集群名稱,集群節點。

與es安裝目錄下的config/elasticsearch.yml一致

spring:    data:      elasticsearch:        cluster-name: myes        #      cluster-nodes: 127.0.0.1:9300        cluster-nodes: hadoop137:9300,hadoop138:9300,hadoop139:9300

編寫程式碼

實體類 TestBean

import org.springframework.data.annotation.Id;  import org.springframework.data.elasticsearch.annotations.Document;  import org.springframework.data.elasticsearch.annotations.Field;  import org.springframework.data.elasticsearch.annotations.FieldType;    import java.io.Serializable;  import java.util.List;    import lombok.Data;  //通過這個註解,可以不用寫gettersetter方法  @Data  //通過這個註解可以聲明一個文檔,指定其所在的索引庫和type  @Document(indexName = "testdoct", type = "testbean")  public class TestBean implements Serializable {      public TestBean() {      }        public TestBean(long id, String name, Integer age, String sex, String desc) {          this.id = id;          this.name = name;          this.age = age;          this.sex = sex;          this.desc = desc;      }        // 必須指定一個id,      @Id      private long id;      // 這裡配置了分詞器,欄位類型,可以不配置,默認也可      @Field(analyzer = "ik_smart", type = FieldType.Text)      private String name;      private Integer age;      @Field(analyzer = "ik_smart", type = FieldType.Text)      private String sex;      @Field(analyzer = "ik_smart", type = FieldType.Text)      private String desc;  }

DAO層 TestDao

import org.springframework.data.domain.Page;  import org.springframework.data.repository.CrudRepository;    import java.util.List;    import top.wintp.estestboot.estestboot.bean.TestBean;    /**   * @author: pyfysf   * <p>   * @qq: 337081267   * <p>   * @CSDN: http://blog.csdn.net/pyfysf   * <p>   * @blog: http://wintp.top   * <p>   * @email: [email protected]   * <p>   * 繼承CRUD,第一個泛型是實體類類型,第二個泛型是id的類型   */  public interface TestDao extends CrudRepository<TestBean, Long> {      List<TestBean> findByName(String name);        List<TestBean> findByNameOrDesc(String text);  }

Service層,TestService (面向介面編程)

import org.springframework.data.domain.Page;  import org.springframework.stereotype.Service;    import java.util.List;    import top.wintp.estestboot.estestboot.bean.TestBean;    /**   * @author: pyfysf   * <p>   * @qq: 337081267   * <p>   * @CSDN: http://blog.csdn.net/pyfysf   * <p>   * @blog: http://wintp.top   * <p>   * @email: [email protected]   * <p>   * @time: 2019/9/17   */  public interface TestService {      Iterable<TestBean> findAll();        void save(List<TestBean> list);        void save(TestBean bean);        List<TestBean> findByName(String text);        List<TestBean> findByNameOrDesc(String name,String desc);  }

service的實現 TestServiceImpl

import org.apache.poi.ss.usermodel.Sheet;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.data.domain.Page;  import org.springframework.stereotype.Service;    import java.util.ArrayList;  import java.util.Date;  import java.util.List;  import java.util.Random;    import cn.hutool.core.io.FileUtil;  import cn.hutool.poi.excel.BigExcelWriter;  import cn.hutool.poi.excel.ExcelReader;  import cn.hutool.poi.excel.ExcelUtil;  import top.wintp.estestboot.estestboot.bean.TestBean;  import top.wintp.estestboot.estestboot.dao.TestDao;  import top.wintp.estestboot.estestboot.service.TestService;    /**   * @author: pyfysf   * <p>   * @qq: 337081267   * <p>   * @CSDN: http://blog.csdn.net/pyfysf   * <p>   * @blog: http://wintp.top   * <p>   * @email: [email protected]   * <p>   * 添加數據是模擬的   */  @Service  public class TestServiceImpl implements TestService {      @Autowired      TestDao testDao;        @Override      public Iterable<TestBean> findAll() {            return testDao.findAll();      }        @Override      public void save(List<TestBean> list) {          list = new ArrayList<>();            String namess = "帆乘   楷棟   鋒楓   海勇   康帆   安禮   曉平   良帆   瑞翱   濤錕   恆勇   鴻馳   帆強   桓柏   鋒寅   博槐   騫琛   桓釗   傑桓   裕楓   福暉   槐仕   奇鵬   駿偉   允濰   乘初   杞郁   柏安   皓宇   駿俠   禮德   哲曉   偉權   祥恆   澄震   浩浩   瑞權   延升   翱楷   鋒軒   馳鵬   杞翱   康鶴   材福   暉銳   信恆   凱錦   誠翱   震福   龍宇   祥帆   梓瑞   林龍   日延   槐翰   日寅   起鴻   杞允   瑞銳   仕星   權銘   吉楷   寅星   林帝   皓仕   卓禮   家盛   海寅   盛胤   年禧   暢安   炳龍   柏暉   誠年   彬坤   禮誠   濡凱   馳晨   恆邦   帆暉   誠華   暉星   恆梓   祿彬   鶴華   錕升   桓浩   振堯   祥寅   楷辰   暄帝   銳梓   恆佑   文安   傑暢   加琛   俊澤   乘馳   祿家   中鶴   家錦   皓初   凱震   文韋   彬澄   起哲   海炳   鶴鋒   賢逸   哲佑   海信   逸俊   炳年   禮郁   濡寅   曉澤   然延   喆加   天梓   澤錕   軒諦   盛翱   晨子   誠吉   梁鶴   仕逸   昇平   奇琛   杞沛   胤邦   辰佑   騫佳   鴻鵬   翱坤   釗峰   哲銳   騰鑫   海陽   爍奇   安芃   浩瑞   星堯   馳炳   安沛   權成   華文   杞晨   柏柔   權彬   禎晨   諦濰   馳安   安日   谷沛   帆華   林翰   然震   琛星   澤杞   澄濤   龍欣   嘉辰   海祿   誠家   帆韋   澄濡   濰延   郁邦   銳禮   蔓材   暢震   騰誠   峰賢   軒濰   凡信   翱年   祜帆   睿吉   禎博   強延   震鑫   邦郁   禧禎   良梁   爍諦   成震   翱顏   加升   榮俊   晨騫   錦槐   爍安   鑫平   沛凱   德升   炳宇   遠俠   暉鵬   騰谷   初帆   林然   中祿   斌顏   顏浩   遠帆   胤然   祜沛   允錕   暢梁   棟材   澤柔   遠銳   杞梁   凱濡   郁槐   家澤   暄乘   年權   文柏   濰禧   澄禧   奇錦   逸然   翰弘   華海   柏辭   瑞星   胤佑   芃嘉   祜胤   逸傑   傑逸   材龍   允升   加韋   逸福   桓辭   楓濡   信然   棟禎" +                  "蓓菡   娜嘉   碧珊   菲昕   芸帆   怡莉   鴻蓮   曦靜   靈玥   橘婧   家曼   鶴麗   嵐琳   格梅   呈夢   璇嘉   月欣   楠敏   瑤麗   茹蓮   杉歆   帆珍   琬彬   蓓昭   函璇   凌歡   歆蔚   妮萱   琛靈   婷媛   琳凌   嵐冬   靜鴻   珍倩   桂楓   玉嵐   紫涵   桃婧   芳璟   韻珠   香萱   冰梅   桂寒   呈曼   梅茹   雯帆   芙明   紫桂   霞玲   蓓莉   霞可   琪香   菲春   美俊   夢梔   鶴婧   帛菲   靜芝   琳沛   玥薇   璟漫   弦茹   彥茜   花梓   歆曦   寒潔   莉梓   穎芙   梓露   玉詩   桃橘   鶴霞   沛漫   月婧   玲陽   雅歡   珍月   璟紫   歆淑   韻琬   月玉   歡彥   寒婭   妍彤   夢萱   蕾芳   心彤   彩妮   寒玲   淑漫   茜桐   春楠   洲茜   月嘉   欣雲   珠香   嵐韻   娜呈   妮弦   芸函   芳寒   萱林   雲琳   蓮菡   碧婭   莉凌   梔茜   蔚妮   惠婧   香心   初莉   穎淑   凡芝   璇靈   可蕾   靜文   彩鶴   芙鑫   花楠   雲夢   菲茹   蓓玥   惠婭   凌芳   柔旭   琛楠   雪娜   蕾詩   芸珠   菡桂   蕾文   桃花   彩詩   彬潔   帆馨   雯春   芝韻   春雅   靜紫   寒橘   冰淑   韻露   昭蓮   詩晨   鈺花   彩月   昕歡   香可   菲婧   橘靜   鈺韻   霞心   彬雅   芙春   菲惠   萱曦   惠楓   舒薇   楠麗   梔珍   琳惠   歆冬   漫月   蓮琛   琬梓   雨美   夢家   倩慧   俊薇   彬璇   敏玉   梔曼   曦倩   蓓蔚   月茜   俊珍   茹帆   璐歡   芝珊   昕舒   婭璐   慧玉   春玥   舒靜   穎楠   淑紫   漫彩   歡曼   芳歆   桂冰   芙薇   旭雅   璇冰   嵐欣   嵐玲   慧錦   克霞   萱麗   采碧   潔昭   采彩   珊雲   漫夢   萱凌   怡文   霞杉   敏怡   莉怡   怡露   格漫   瑤薇   沛菲   彥夢   妮馨   菲萱   敏桐   鶴菡   彬蓓   凌彤   珊莉   漫依   琪蓮   欣霞   璟心   梅薇   寒蓓   倩梓   采娜   琬雯   楓梅   花格   馨可   杉璐   舒婭   沛香   穎茹   格玲   花柏   雨璟   欣薇";            String[] names = namess.split("\s+");            String[] descArr = {"大家好,我是雨天,因為剛好出生在雨天,老爸又剛好姓夏,於是「下雨天」就首發出場了,而且媽媽也希望我如雨後春筍、天天向上哦!呵呵後來因為一部分人實在不忍心在晴朗的天氣里叫我雨天,為避免引起「混亂」,就只好捨棄了這個頗有個性的簡單名字,退而成「小名「了。我的大名也簡單,其實就一個「翌」字,因為我出生的日子剛好是爸爸媽媽結婚2周年紀念日的第二日。「夏翌」諧音寧波話「暇意」,大家希望我暇暇意意,呵呵,有點嫌」翌」字太文縐縐,就把它給拆了,一分為二成羽立了。"                  , "大家都說我是個陽光女孩,因為我是開心果啊。我老是坐不住,呵呵,能跟小椅子成為好朋友,是老師和爸爸媽媽現在的最大心愿。我喜歡跳舞,但最好能跟著音樂自己起舞,不用按老師的要求練基本功;我喜歡畫畫,但最好是信手塗鴉,把小朋友的臉畫成綠色也沒關係;我喜歡溜冰,但最有趣的還是約上三五好友,一起練習如何摔跤……"                  , "昀昀是我在媽媽肚子里時的小名哦,我的大名叫曹鐵瀛,媽媽懷我的時候和單位里的阿姨們玩牌經常是百戰百勝,阿姨們說是因為我的緣故,乾脆就叫「天贏」好了,爸媽取其諧音,就變成了「鐵瀛」"                  , "嘿!我——21號來報到了!智誥、誥誥、阿誥,你們愛怎麼叫就怎麼叫吧!反正都是我!我的名字是奶奶請一名先生取的,雖然有點迷信,但寄託了全家人的祝福!"                  , "還是汽車發燒友,小轎車、大卡車、集裝箱、大客車、翻斗車、壓路機……應有盡有(就差拖拉機還沒有報到)。我常在家練習倒車、移庫、爬坡、過單軌橋,考取駕照不成問題!!當然我也模擬製造幾起車禍,掉進大河,深溝,追尾事故,因為那時我又能大顯身手,汽車的零件裝了又拆,拆了又裝……哈哈!!角角落落都是我的傑作,缺胳膊少腿的,七零八落的,儘管汽車多,可完完整整的沒幾輛!這下,又有理由去買車啦!"                  , "我還喜歡畫畫。從小我就拿著筆畫一個個的大圓圈,每天樂此不疲,整整畫了半年多圓圈呢!夠有毅力的吧!老師說我構圖線條流暢,就是那樣練出來的哦!以後我一定會繼續努力的!可是我不太喜歡看書,媽媽讓我看書,我老是心不在焉,左顧右盼,常常惹她不高興,可我就是不喜歡嘛!"                  , "我的性格有點內向、靦腆、不喜歡「顯山露水」。我最喜歡體育項目了,最「痴迷」的就是體育頻道:乒乓球、羽毛球、撞球、足球、籃球、跳水~~,當然我也喜歡打牌(這可是遺傳)。"                  , "我的個子很高,被稱為「帥哥」,因此彼得女孩子的歡心哦,等我長大了,我要娶七個「老婆」,其中三個為:外婆、爸爸和媽媽。我的目標是考上北大。n"                  , "我當時的第一反應是:這兩個字可以跟名人的名字做一個聯繫,然後做一個介紹。我說你介紹的時候可以跟別人講:"          };            Random random = new Random();            //模擬數據          for (int i = 0; i < 100; i++) {              int i1 = random.nextInt(names.length);              int i2 = random.nextInt(descArr.length);              //注意這裡 第一個參數是id 所以無論你運行多少次,都只會添加100條數據,如果id存在es更新,不存在添加              TestBean testBean = new TestBean(i, names[i1], i, String.valueOf(i % 2), descArr[i2]);                list.add(testBean);          }            testDao.saveAll(list);      }        @Override      public void save(TestBean bean) {          testDao.save(bean);      }        @Override      public List<TestBean> findByName(String text) {          return testDao.findByName(text);      }        @Override      public List<TestBean> findByNameOrDesc(String text) {          return testDao.findByNameOrDesc(text,text);      }  }

TestController

import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RestController;    import java.util.List;    import top.wintp.estestboot.estestboot.bean.TestBean;  import top.wintp.estestboot.estestboot.service.TestService;    /**   * @author: pyfysf   * <p>   * @qq: 337081267   * <p>   * @CSDN: http://blog.csdn.net/pyfysf   * <p>   * @blog: http://wintp.top   * <p>   * @email: [email protected]   * <p>   */  @RestController  @RequestMapping("/testes")  public class TestController {        @Autowired      TestService testService;        @RequestMapping("findAll")      public Iterable<TestBean> findAll() {            return testService.findAll();      }        @RequestMapping("list")      public String save() {          List<TestBean> list = null;          testService.save(list);            return "success";      }        @RequestMapping("save")      public void save(TestBean bean) {          testService.save(bean);      }        @RequestMapping("findByName")      public List<TestBean> findByName(String name) {          return testService.findByName(name);      }        @RequestMapping("findByNameOrDesc")      public List<TestBean> findByNameOrDesc(String text) {          return testService.findByNameOrDesc(text);      }    }

測試

啟動程式會自動創建testdoc索引庫

通過kibana查看:

調用項目介面:http://localhost:8080/testes/list

表示添加成功。

可以通過kibana介面查看並搜索數據,也可以直接調用我們自己寫的findAll介面進行查詢。

測試findByName: http://localhost:8080/testes/findByName

測試findByNameOrDesc:http://localhost:8080/testes/findByNameOrDesc?text=浩

查詢名字中或者desc中含有「浩」的數據

結語

這就是SpringBoot集成ES的基本步驟,相比較於自己引入ES的依賴要簡單的很多。如果對你有幫助,請分享出去吧。對於更多的JPA的方法命名規則請查看JPA官方介紹。大致上都和SQL語句差不多。