SpringBoot集成ElasticSearch

1. ElasticSearch

1.1 ElasticSearch的簡(jiǎn)單介紹

ElasticSearch 是開(kāi)源搜索平臺(tái)領(lǐng)域的一個(gè)新成員辜昵。 ElasticSearch(簡(jiǎn)稱 ES) 是一個(gè)基于 Lucene 構(gòu)建的開(kāi)源难菌,分布式泽论,RESTful 搜索引擎。 具有搜索實(shí)時(shí)甚侣、穩(wěn)定福压、可靠和快速的特點(diǎn),并且安裝使用方便疯特。 支持通過(guò) HTTP 請(qǐng)求哗魂,使用 JSON 進(jìn)行數(shù)據(jù)索引肛走。

1.2 ElasticSearch的一些概念的介紹

(1). 索引: 一個(gè)索引就是一個(gè)擁有幾分相似特征的文檔的集合。一個(gè)索引由一個(gè)名字來(lái)標(biāo)識(shí)(必須全部是小寫(xiě)字母的)录别,并且當(dāng)我們要對(duì)對(duì)應(yīng)于這個(gè)索引中的文檔進(jìn)行索引朽色、搜索邻吞、更新和刪除的時(shí)候,都要使用到這個(gè)名字葫男。在一個(gè)集群中抱冷,可以定義任意多的索引。索引名稱必須要全部小寫(xiě)梢褐,也不能以下劃線開(kāi)頭旺遮,不能包含逗號(hào)。類似于關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)庫(kù)盈咳;
(2). 類型:在一個(gè)索引中耿眉,可以定義一種或多種類型。一個(gè)類型是你的索引的一個(gè)邏輯上的分類/分區(qū),通常鱼响,會(huì)為具有一組共同字段的文檔定義一個(gè)類型鸣剪,每一個(gè)類型都擁有自己的映射(mapping)或者結(jié)構(gòu)定義,它們定義了當(dāng)前類型下的數(shù)據(jù)結(jié)構(gòu)丈积,類似于數(shù)據(jù)庫(kù)表中的列筐骇。劃分時(shí)需要注意一些限制條件,例如不同的文檔類型對(duì)同一字段不能設(shè)置為不同的字段類型;類似于關(guān)系型數(shù)據(jù)庫(kù)中的的表江滨;
(3). 文檔:一個(gè)文檔是一個(gè)可被索引的基礎(chǔ)信息單元铛纬。文檔以JSON(JavascriptObject Notation)格式來(lái)表示,一個(gè)文檔不只包含了數(shù)據(jù)牙寞。它還包含了元數(shù)據(jù)(metadata) —— 關(guān)于文檔的信息饺鹃。有三個(gè)元數(shù)據(jù)元素是必須存在的,它們是:id是一個(gè)字符串间雀, _index 和 _type 悔详,他們可以組合起來(lái)鎖定Elasticsearch中一個(gè)特定的文檔。

1.3 ElasticSearch與關(guān)系型數(shù)據(jù)庫(kù)的對(duì)照關(guān)系

DB -> Databases -> Tables -> Rows -> Columns 
ES -> Indices -> Types -> Documents -> Fields

3.4 ElasticSearch中對(duì)索引的一些常用操作

1. 獲取Elasticsearch中所有的index:

curl -XGET 'localhost:9200/_cat/indices?v&pretty'

2. 獲取某索引下所有的type:

獲取elasticsearch索引下所有的type定義
curl -XGET 'localhost:9200/elasticsearch/_mapping'

3. 刪除索引:

刪除elasticsearch1索引
curl -XDELETE 'localhost:9200/elasticsearch1?pretty'

4. 刪除某索引下的某type數(shù)據(jù):

刪除索引elasticsearch下的article類型
curl -XDELETE 'http://localhost:9200/elasticsearch/article/'

5. 查看某索引的某type下所有的數(shù)據(jù):

查找elasticsearch索引中所有的類型為Company的數(shù)據(jù)
http://localhost:9200/elasticsearch/Company/_search

3.5 ElasticSearch所遇到過(guò)的問(wèn)題

1 當(dāng)查詢的時(shí)候如果沒(méi)有設(shè)置from和size惹挟,那么默認(rèn)只會(huì)查出10條茄螃,不是我們想要的果

解決辦法: 通過(guò)先查出總的條數(shù),再將其值設(shè)置為size连锯;

2 查詢多條數(shù)據(jù)時(shí)遇到過(guò)的問(wèn)題:

錯(cuò)誤提示信息:Result window is too large
解決方案: 主要是修改index.max_result_window參數(shù)归苍,默認(rèn)為10000
命令:curl -XPUT http://127.0.0.1:9200/cmdb-now/_settings -d '{ "index" : { "max_result_window" : 100000000}}'

3 各種版本與api不匹配的問(wèn)題

解決方式:上網(wǎng)找,以及測(cè)試api與版本

1.6 ElasticSearch架構(gòu)及其支持的客戶端連接方式

Es架構(gòu)圖

方式一:REST API 运怖,端口 9200:這種連接方式對(duì)應(yīng)于架構(gòu)圖中的RESTful style API這一層拼弃,這種客戶端的連接方式是RESTful風(fēng)格的,使用http的方式進(jìn)行連接

方式二:Transport 摇展,端口 9300:這種連接方式對(duì)應(yīng)于架構(gòu)圖中的Transport這一層吻氧,這種客戶端連接方式是直接連接ES的節(jié)點(diǎn),使用TCP的方式進(jìn)行連接;(ES7.0將會(huì)關(guān)閉Transport,8.0將完全刪除盯孙,取而代之的是High Level REST Client)

ElasticSearch提供了兩個(gè)JAVA REST client 版本:
Java Low Level REST Client: 低級(jí)別的REST客戶端鲁森,通過(guò)http與集群交互,需自己編組請(qǐng)求JSON串振惰,及解析響應(yīng)JSON串歌溉。兼容所有ES版本。

Java High Level REST Client: 高級(jí)別的REST客戶端骑晶,基于低級(jí)別的REST客戶端痛垛,增加了編組請(qǐng)求JSON串、解析響應(yīng)JSON串等相關(guān)api桶蛔。使用的版本需要保持和ES服務(wù)端的版本一致榜晦,否則會(huì)有版本問(wèn)題。

1.7 代碼示例

    
    /**
     * @description: es工具類
     * @author: Guimu
     * @create: 2018/07/31 11:47:55
     **/
    @Component
    public class EsUtils {
        @Autowired
        private RestHighLevelClient client;
        private static final String CURRENT_MODEL_PACKAGE_NAME = "com.yy.elasticsearch.model.";
        private static final String DEFAULT_INDEX = "elasticsearch";
    
        /**
         * @Description: 根據(jù)Base 子類數(shù)據(jù)產(chǎn)生一個(gè)IndexRequest數(shù)據(jù)
         * @Param: [source]
         * @Return: org.elasticsearch.action.index.IndexRequest
         * @Author: Guimu
         * @Date: 2018/7/31  下午5:30
         */
        private IndexRequest indexRequestGenerater(Base source) {
            IndexRequest indexRequest = null;
            if (StringUtils.isEmpty(source.getIndex())) {
                source.setIndex(DEFAULT_INDEX);
            }
            try {
                String[] tempArr = source.getClass().getName().split("\\.");
                source.setType(tempArr[tempArr.length - 1]);
                indexRequest = new IndexRequest(source.getIndex(), source.getType());
                indexRequest.source(JacksonUtil.getString(source), XContentType.JSON);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return indexRequest;
        }
    
        /**
         * @Description: 批量存儲(chǔ)接口, boolean  表示保存成功與否
         * @Param: [bases]
         * @Return: boolean
         * @Author: Guimu
         * @Date: 2018/7/31  下午5:32
         */
        public boolean batchSave(List<? extends Base> bases) {
            BulkRequest bulkRequest = new BulkRequest();
            bases.forEach(el -> bulkRequest.add(indexRequestGenerater(el)));
            boolean flag = false;
            try {
                BulkResponse bulkItemResponses = client.bulk(bulkRequest);
                flag = "created".equalsIgnoreCase(bulkItemResponses.getItems()[0].getResponse().getResult().name());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return flag;
        }
    
        /**
         * @Description: 保存單個(gè)索引文檔數(shù)據(jù)
         * @Param: [source]
         * @Return: boolean
         * @Author: Guimu
         * @Date: 2018/7/31  下午2:05
         */
        public boolean singleSave(Base source) {
            IndexRequest singleRequest;
            boolean flag = false;
            try {
                singleRequest = indexRequestGenerater(source);
                IndexResponse indexResponse = client.index(singleRequest);
                flag = "created".equalsIgnoreCase(indexResponse.getResult().name());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return flag;
        }
    
        /**
         * @Description: 模糊匹配名字, 精確匹配corpId
         * @Param: [name, corpId]
         * @Return: java.util.List<com.yy.elasticsearch.model.Base>
         * @Author: Guimu
         * @Date: 2018/7/31  下午2:21
         */
        public List<Base> queryLikeNameAndCorpId(String name, String type, Long corpId) {
            MatchPhraseQueryBuilder mb1 = QueryBuilders.matchPhraseQuery("corpId", corpId);
            MatchPhraseQueryBuilder mb2 = QueryBuilders.matchPhraseQuery("name", "*" + name + "*");
            QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(mb1).must(mb2);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(queryBuilder);
            SearchRequest searchRequest = new SearchRequest(DEFAULT_INDEX);
            searchRequest.types(type);
            searchRequest.source(searchSourceBuilder);
            return baseQuery(searchRequest);
        }
    
        /**
         * @Description: 查找指定corpId和type的所有數(shù)據(jù)
         * @Param: [name, corpId]
         * @Return: java.util.List<com.yy.elasticsearch.model.Base>
         * @Author: Guimu
         * @Date: 2018/7/31  下午2:21
         */
        public List<Base> queryByCorpId(String type, Long corpId) {
            MatchPhraseQueryBuilder mb = QueryBuilders.matchPhraseQuery("corpId", corpId);
            QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(mb);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(queryBuilder);
            SearchRequest searchRequest = new SearchRequest(DEFAULT_INDEX);
            searchRequest.types(type);
            searchRequest.source(searchSourceBuilder);
            return baseQuery(searchRequest);
        }
    
        /**
         * @Description: 查詢?cè)撍饕? 指定type的所有數(shù)據(jù)
         * @Param: [index, type]
         * @Return: java.util.List<com.yy.elasticsearch.model.Base>
         * @Author: Guimu
         * @Date: 2018/7/31  下午6:06
         */
        public List<Base> findAll(String index, String type) {
            SearchRequest searchRequest = new SearchRequest(index);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.from(0);
            searchSourceBuilder.size(this.getCount(searchRequest).intValue());
            searchRequest.source(searchSourceBuilder);
            //查詢?nèi)縳xxxx
            searchRequest.types(type);
            return baseQuery(searchRequest);
        }
    
        /**
         * @Description: 獲取該查詢請(qǐng)求的總條數(shù)total
         * @Param: [searchRequest]
         * @Return: java.lang.Long
         * @Author: Guimu
         * @Date: 2018/7/31  下午4:58
         */
        private Long getCount(SearchRequest searchRequest) {
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.from(0);
            searchSourceBuilder.size(1);
            searchRequest.source(searchSourceBuilder);
            try {
                SearchResponse response = client.search(searchRequest);
                return response.getHits().getTotalHits();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return -1L;
        }
    
        /**
         * @Description: 私有的基礎(chǔ)查詢, 提高代碼復(fù)用性
         * @Param: [searchRequest]
         * @Return: java.util.List<com.yy.elasticsearch.model.Base>
         * @Author: Guimu
         * @Date: 2018/7/31  下午6:15
         */
        private List<Base> baseQuery(SearchRequest searchRequest) {
            try {
                SearchResponse response = client.search(searchRequest);
                return Arrays.asList(response.getHits().getHits()).stream().map(el -> {
                    Map<String, Object> map = el.getSource();
                    Class clazz;
                    Base base = null;
                    try {
                        map.put("id", el.getId());
                        clazz = Class.forName(CURRENT_MODEL_PACKAGE_NAME + map.get("type").toString());
                        base = (Base) JacksonUtil.getObject(JacksonUtil.getString(map), clazz);
                    } catch (IOException | ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    return base;
                }).collect(Collectors.toList());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * @Description: 基礎(chǔ)刪除接口, 支持Base的所有子類
         * @Param: [base]
         * @Return: boolean
         * @Author: Guimu
         * @Date: 2018/7/31  下午6:32
         */
        public boolean deleteBase(Base base) {
            DeleteRequest deleteRequest = new DeleteRequest(base.getIndex(), base.getType(), base.getId());
            boolean flag = false;
            try {
                DeleteResponse deleteResponse = client.delete(deleteRequest);
                flag = "deleted".equalsIgnoreCase(deleteResponse.getResult().name());
                System.out.println(deleteResponse);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return flag;
        }
    
        /**
         * @Description: 此處傳入的base的所有值都是全的羽圃,沒(méi)有null值
         * @Param: [base]
         * @Return: boolean
         * @Author: Guimu
         * @Date: 2018/8/1  上午10:02
         */
        public boolean updateBase(Base base) {
            UpdateRequest updateRequest = new UpdateRequest(base.getIndex(), base.getType(), base.getId());
            boolean flag = false;
            try {
                updateRequest.doc(JacksonUtil.getString(base), XContentType.JSON);
                UpdateResponse updateResponse = client.update(updateRequest);
                flag = "updated".equalsIgnoreCase(updateResponse.getResult().name());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return flag;
        }
    
        /**
         * @Description: 根據(jù)名字, type, corpId 進(jìn)行精確查詢Base數(shù)據(jù),沒(méi)找到則返回 null
         * @Param: [name, type, corpId]
         * @Return: com.yy.elasticsearch.model.Base
         * @Author: Guimu
         * @Date: 2018/8/1  上午9:35
         */
        public <T extends Base> T queryOneBase(String name, String type, Long corpId) {
            MatchPhraseQueryBuilder mb = QueryBuilders.matchPhraseQuery("corpId", corpId);
            MatchPhraseQueryBuilder mb1 = QueryBuilders.matchPhraseQuery("name", name);
            QueryBuilder queryBuilder = QueryBuilders.boolQuery().must(mb).must(mb1);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(queryBuilder);
            SearchRequest searchRequest = new SearchRequest(DEFAULT_INDEX);
            searchRequest.types(type);
            searchRequest.source(searchSourceBuilder);
            Base rebase = null;
            try {
                rebase = baseQuery(searchRequest).get(0);
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
            Class<T> aClass = null;
            try {
                aClass = (Class<T>) Class.forName(CURRENT_MODEL_PACKAGE_NAME + type);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null == rebase ? null : aClass.cast(rebase);
        }
    
        public static String getDefaultIndex() {
            return DEFAULT_INDEX;
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乾胶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子朽寞,更是在濱河造成了極大的恐慌识窿,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脑融,死亡現(xiàn)場(chǎng)離奇詭異喻频,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)肘迎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)甥温,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人妓布,你說(shuō)我怎么就攤上這事姻蚓。” “怎么了匣沼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵狰挡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我释涛,道長(zhǎng)加叁,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任唇撬,我火速辦了婚禮它匕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘窖认。我一直安慰自己豫柬,他們只是感情好愈污,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著轮傍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪首装。 梳的紋絲不亂的頭發(fā)上创夜,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音仙逻,去河邊找鬼驰吓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛系奉,可吹牛的內(nèi)容都是我干的檬贰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缺亮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼翁涤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起萌踱,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤葵礼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后并鸵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鸳粉,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年园担,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了届谈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弯汰,死狀恐怖艰山,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咏闪,我是刑警寧澤程剥,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站汤踏,受9級(jí)特大地震影響织鲸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜溪胶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一搂擦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哗脖,春花似錦瀑踢、人聲如沸扳还。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)氨距。三九已至,卻和暖如春棘劣,著一層夾襖步出監(jiān)牢的瞬間俏让,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工茬暇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留首昔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓糙俗,卻偏偏與公主長(zhǎng)得像勒奇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巧骚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 基礎(chǔ)概念 Elasticsearch有幾個(gè)核心概念赊颠,從一開(kāi)始理解這些概念會(huì)對(duì)整個(gè)學(xué)習(xí)過(guò)程有莫大的幫助。 接近實(shí)時(shí)(...
    山天大畜閱讀 2,105評(píng)論 0 4
  • 一劈彪、環(huán)境搭建 軟件版本: Linux:centos7 64bit JDK:1.8.0 elasticsearch:...
    lailai900201閱讀 3,570評(píng)論 0 12
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理巨税,服務(wù)發(fā)現(xiàn),斷路器粉臊,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • 簡(jiǎn)介 Elasticsearch是一個(gè)高可擴(kuò)展的開(kāi)源全文搜索和分析引擎草添,它允許存儲(chǔ)、搜索和分析大量的數(shù)據(jù)扼仲,并且這個(gè)...
    零度沸騰_yjz閱讀 5,521評(píng)論 0 8
  • 離開(kāi)九天之后远寸,昨天晚上返回杭州。這段時(shí)間萬(wàn)伊若發(fā)生了很大變化屠凶,她依然認(rèn)得我驰后,一進(jìn)門(mén)就對(duì)著我呵呵地笑。 萬(wàn)伊若已經(jīng)會(huì)...
    wanjunping閱讀 243評(píng)論 0 0