第九篇 : SpringBoot 整合 elasticsearch

文章首發(fā)于微信公眾號《程序員果果》
地址:https://mp.weixin.qq.com/s/f9eE7jsPNWAr1gQ0iF-kDw
本篇源碼:https://github.com/gf-huanchupk/SpringBootLearning

一擂橘、簡介

我們的應(yīng)用經(jīng)常需要添加檢索功能胳搞,開源的 ElasticSearch 是目前全文搜索引擎的 首選踪旷。他可以快速的存儲召庞、搜索和分析海量數(shù)據(jù)。Spring Boot通過整合Spring Data ElasticSearch為我們提供了非常便捷的檢索功能支持;
Elasticsearch是一個分布式搜索服務(wù)娄琉,提供Restful API,底層基于Lucene,采用 多shard(分片)的方式保證數(shù)據(jù)安全凰盔,并且提供自動resharding的功能,github 等大型的站點也是采用了ElasticSearch作為其搜索服務(wù)倦春,

二、安裝elasticsearch

我們采用 docker鏡像安裝的方式落剪。

#下載鏡像
docker pull elasticsearch
#啟動鏡像睁本,elasticsearch 啟動是會默認(rèn)分配2G的內(nèi)存 ,我們啟動是設(shè)置小一點忠怖,防止我們內(nèi)存不夠啟動失敗
#9200是elasticsearch 默認(rèn)的web通信接口呢堰,9300是分布式情況下,elasticsearch個節(jié)點通信的端口
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es01 5c1e1ecfe33a

訪問 127.0.0.1:9200 如下圖凡泣,說明安裝成功

三枉疼、elasticsearch的一些概念

  • 員工文檔 的形式存儲為例:一個文檔代表一個員工數(shù)據(jù)。存儲數(shù)據(jù)到 ElasticSearch 的行為叫做索引 鞋拟,但在索引一個文檔之前骂维,需要確定將文檔存 儲在哪里。
  • 一個 ElasticSearch 集群可以 包含多個索引 贺纲,相應(yīng)的每個索引可以包含多個類型航闺。這些不同的類型存儲著多個文檔 ,每個文檔又有 多個 屬性 猴誊。
  • 類似關(guān)系:
  • 索引-數(shù)據(jù)庫
  • 類型-表
  • 文檔-表中的記錄 – 屬性-列

elasticsearch使用可以參早官方文檔潦刃,在這里不在講解。

四懈叹、整合 elasticsearch

創(chuàng)建項目 springboot-elasticsearch乖杠,引入web支持
SpringBoot 提供了兩種方式操作elasticsearch,Jest 和 SpringData澄成。

Jest 操作 elasticsearch

Jest是ElasticSearch的Java HTTP Rest客戶端胧洒。

ElasticSearch已經(jīng)有一個Java API笆包,ElasticSearch也在內(nèi)部使用它,但是Jest填補了空白略荡,它是ElasticSearch Http Rest接口缺少的客戶端庵佣。

1. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.gf</groupId>
    <artifactId>springboot-elasticsearch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-elasticsearch</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>5.3.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

2. application.properties

spring.elasticsearch.jest.uris=http://127.0.0.1:9200

3. Article

package com.gf.entity;


import io.searchbox.annotations.JestId;

public class Article {

    @JestId
    private Integer id;
    private String author;
    private String title;
    private String content;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder( "{\"Article\":{" );
        sb.append( "\"id\":" )
                .append( id );
        sb.append( ",\"author\":\"" )
                .append( author ).append( '\"' );
        sb.append( ",\"title\":\"" )
                .append( title ).append( '\"' );
        sb.append( ",\"content\":\"" )
                .append( content ).append( '\"' );
        sb.append( "}}" );
        return sb.toString();
    }


}

4. springboot測試類

package com.gf;

import com.gf.entity.Article;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootElasticsearchApplicationTests {

    @Autowired
    JestClient jestClient;

    @Test
    public void createIndex() {
        //1. 給ES中索引(保存)一個文檔
        Article article = new Article();
        article.setId( 1 );
        article.setTitle( "好消息" );
        article.setAuthor( "張三" );
        article.setContent( "Hello World" );

        //2. 構(gòu)建一個索引
        Index index = new Index.Builder( article ).index( "gf" ).type( "news" ).build();
        try {
            //3. 執(zhí)行
            jestClient.execute( index );
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void search() {
        //查詢表達(dá)式
        String query = "{\n" +
                "    \"query\" : {\n" +
                "        \"match\" : {\n" +
                "            \"content\" : \"hello\"\n" +
                "        }\n" +
                "    }\n" +
                "}";

        //構(gòu)建搜索功能
        Search search = new Search.Builder( query ).addIndex( "gf" ).addType( "news" ).build();

        try {
            //執(zhí)行
            SearchResult result = jestClient.execute( search );
            System.out.println(result.getJsonString());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

Jest的更多api ,可以參照github的文檔:https://github.com/searchbox-io/Jest

SpringData 操作 elasticsearch

1. application.properties

spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

2. Book

package com.gf.entity;

@Document( indexName = "gf" , type = "book")
public class Book {
    private Integer id;
    private String bookName;
    private String author;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder( "{\"Book\":{" );
        sb.append( "\"id\":" )
                .append( id );
        sb.append( ",\"bookName\":\"" )
                .append( bookName ).append( '\"' );
        sb.append( ",\"author\":\"" )
                .append( author ).append( '\"' );
        sb.append( "}}" );
        return sb.toString();
    }
    
}

3. BookRepository

package com.gf.repository;


import com.gf.entity.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

public interface BookRepository extends ElasticsearchRepository<Book, Integer>{

    List<Book> findByBookNameLike(String bookName);

}

4. springboot 測試類

package com.gf;

import com.gf.entity.Article;
import com.gf.entity.Book;
import com.gf.repository.BookRepository;
import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.IOException;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootElasticsearchApplicationTests {

    @Autowired
    BookRepository bookRepository;
    
    @Test
    public void createIndex2(){
        Book book = new Book();
        book.setId(1);
        book.setBookName("西游記");
        book.setAuthor( "吳承恩" );
        bookRepository.index( book );
    }

    @Test
    public void useFind() {
        List<Book> list = bookRepository.findByBookNameLike( "游" );
        for (Book book : list) {
            System.out.println(book);
        }

    }

}

我們啟動測試 汛兜,發(fā)現(xiàn)報錯 巴粪。


這個報錯的原因是springData的版本與我elasticsearch的版本有沖突,下午是springData官方文檔給出的適配表粥谬。


我們使用的springdata elasticsearch的 版本是3.1.3 肛根,對應(yīng)的版本應(yīng)該是6.2.2版本,而我們是的 elasticsearch 是 5.6.9漏策,所以目前我們需要更換elasticsearch的版本為6.X

docker pull elasticsearch:6.5.1
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es02 鏡像ID

訪問127.0.0.1:9200


集群名為docker-cluster派哲,所以我們要修改application.properties的配置了

spring.data.elasticsearch.cluster-name=docker-cluster
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

我們再次進行測試,測試可以通過了 掺喻。我們訪問http://127.0.0.1:9200/gf/book/1芭届,可以得到我們存入的索引信息。

源碼下載:https://github.com/gf-huanchupk/SpringBootLearning

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末感耙,一起剝皮案震驚了整個濱河市褂乍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌即硼,老刑警劉巖逃片,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異只酥,居然都是意外死亡褥实,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門裂允,熙熙樓的掌柜王于貴愁眉苦臉地迎上來损离,“玉大人,你說我怎么就攤上這事叫胖〔莞裕” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵瓮增,是天一觀的道長怎棱。 經(jīng)常有香客問我,道長绷跑,這世上最難降的妖魔是什么拳恋? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮砸捏,結(jié)果婚禮上谬运,老公的妹妹穿的比我還像新娘隙赁。我一直安慰自己,他們只是感情好梆暖,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布伞访。 她就那樣靜靜地躺著,像睡著了一般轰驳。 火紅的嫁衣襯著肌膚如雪厚掷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天级解,我揣著相機與錄音冒黑,去河邊找鬼。 笑死勤哗,一個胖子當(dāng)著我的面吹牛抡爹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播芒划,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼冬竟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腊状?” 一聲冷哼從身側(cè)響起诱咏,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缴挖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焚辅,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡映屋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了同蜻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棚点。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖湾蔓,靈堂內(nèi)的尸體忽然破棺而出瘫析,到底是詐尸還是另有隱情,我是刑警寧澤默责,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布贬循,位于F島的核電站,受9級特大地震影響桃序,放射性物質(zhì)發(fā)生泄漏杖虾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一媒熊、第九天 我趴在偏房一處隱蔽的房頂上張望奇适。 院中可真熱鬧坟比,春花似錦、人聲如沸嚷往。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皮仁。三九已至籍琳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魂贬,已是汗流浹背巩割。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留付燥,地道東北人宣谈。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像键科,于是被迫代替她去往敵國和親闻丑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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