41. 從零開始學springboot整合ElasticSearch

Elastic介紹

在2018年10月5日,一個做數據搜索服務的軟件初創(chuàng)公司 Elastic,在納斯達克上市。

image

而我們所熟悉的 ElasticSearch,正是 Elastic 公司最出名的產品之一,其中還包括有分布式日志解決方案 ELK(Elastic Search、Logstash、Kibana)、Beats、ECE等。

那 ElasticSearch 究竟是干啥的呢?

本質其實是一個基于 Lucene 開發(fā)的搜索服務器,它提供了一個基于 RESTful web 接口的分布式多用戶能力的全文搜索引擎,能夠達到實時搜索、穩(wěn)定、可靠、快速、安裝使用方便等特點。

同時,作為 Apache 許可條款下的開放源碼,目前已經成為一種流行的企業(yè)級搜索引擎。

既然在企業(yè)開發(fā)中如此流行,肯定少不了 Springboot 的參與,今天我們就一起來探討一下 SpringBoot 與 ElasticSearch 的整合,看看它是否真的如所介紹的那樣優(yōu)秀!

本文主要介紹分為以下幾個部分:

  • 第一部分:環(huán)境準備,安裝ElasticSearch,安裝 ElasticSearch-head 插件可視化web界面
  • 第二部分:SpringBoot 整合 ElasticSearch 開發(fā)
  • 第三部分:CRUD 測試

ElasticSearch 安裝

為了和真實環(huán)境一致,我們采用CentOS7來部署 ElasticSearch 服務。

建議把所需的安裝包,手動從網上下載下來,因為“都懂的”原因!所以服務器下載 ElasticSearch 安裝包非常慢.

登錄https://www.elastic.co/cn/downloads/elasticsearch,選擇相應的系統環(huán)境下載軟件包,咸魚君用的是CentOS,所以選擇Linux環(huán)境。

image
安裝JDK(已經安裝過,可以跳過)

Elasticsearch 是用 Java 語言開發(fā)的,所以在安裝之前,需要先安裝一下JDK

yum -y install java-1.8.0-openjdk

查看java安裝情況

java -version
image.png
安裝ElasticSearch

進入對應文件夾,安裝ElasticSearch

rpm -ivh elasticsearch-6.1.0.rpm

查找安裝路徑

rpm -ql elasticsearch

一般是裝在/usr/share/elasticsearch/下。

設置data的目錄

創(chuàng)建/data/es-data目錄,用于elasticsearch數據的存放

mkdir -p /data/es-data

修改該目錄的擁有者為elasticsearch

chown -R elasticsearch:elasticsearch /data/es-data
設置log的目錄
mkdir -p /log/es-log

修改該目錄的擁有者為elasticsearch

chown -R elasticsearch:elasticsearch /log/es-log
修改配置文件elasticsearch.yml
vim /etc/elasticsearch/elasticsearch.yml

修改如下內容:

#設置節(jié)點名稱
cluster.name: my-es

#設置data存放的路徑為/data/es-data
path.data: /data/es-data

#設置logs日志的路徑為/log/es-log
path.logs: /log/es-log

#設置內存不使用交換分區(qū),配置了bootstrap.memory_lock為true時反而會引發(fā)9200不會被監(jiān)聽,原因不明
bootstrap.memory_lock: false

#設置允許所有ip可以連接該elasticsearch
network.host: 0.0.0.0

#開啟監(jiān)聽的端口為9200
http.port: 9200

#增加新的參數,為了讓elasticsearch-head插件可以訪問es (5.x版本,如果沒有可以自己手動加)
http.cors.enabled: true
http.cors.allow-origin: "*"
啟動elasticsearch

啟動

systemctl start elasticsearch

查看狀態(tài)

systemctl status elasticsearch

設置開機啟動

systemctl enable elasticsearch

啟動成功之后,測試服務是否開啟

curl -X GET http://localhost:9200

返回如下信息,說明安裝、啟動成功了

image.png

同時也可以遠程測試一下,如果網絡被拒絕,檢查防火墻是否開啟

查詢防火墻狀態(tài)

firewall-cmd --state

如果狀態(tài)是active表示已經開啟,可以將其關閉

關閉防火墻

systemctl stop firewalld.service

如果不想開機啟動,可以輸入如下命令

禁止firewall開機啟動

systemctl disable firewalld.service

ElasticSearch-head 安裝

上面我們介紹了 ElasticSearch 的安裝,但是只能通過接口去查詢數據,能不能通過可視化界面來查詢數據呢?

ElasticSearch-head,就是一個提供可視化界面的 ElasticSearch 插件,使用 Html5 開發(fā),本質上還是一個 nodejs 的工程,因此在使用之前需要先安裝 nodeJs。

安裝 nodeJs

下載nodeJS

wget https://nodejs.org/dist/v10.9.0/node-v10.9.0-linux-x64.tar.gz

解壓下載包

tar -zxvf node-v10.9.0-linux-x64.tar.gz

移動解壓之后的文件夾到/usr/local

mv node-v10.9.0-linux-x64 /usr/local/nodejs

創(chuàng)建軟鏈接,讓npmnode命令全局生效

ln -s /usr/local/nodejs/bin/node /usr/bin/node
ln -s /usr/local/nodejs/bin/npm /usr/bin/npm

查看nodejs是否安裝成功

node -v
npm -v
image
安裝 elasticsearch-head

如果未安裝git ,則先安裝git工具

yum install –y git

查看git安裝情況

git --version
image

從 gitHub 上拉取 elasticsearch-head 插件代碼

git clone https://github.com/mobz/elasticsearch-head.git

進入elasticsearch-head文件夾

cd elasticsearch-head

因為npm安裝非常非常慢,所以在這里先安裝淘寶源地址,命令如下:

npm install cnpm -g --registry=https://registry.npm.taobao.org

創(chuàng)建cnpm軟鏈接,不然執(zhí)行下面執(zhí)行命令會報錯

ln -s /usr/local/nodejs/bin/cnpm /usr/local/bin/cnpm

使用cnpm命令下載安裝項目所需要的插件

cnpm install

大概2分鐘之后就安裝好了,安裝完成之后,修改配置信息

vim _site/app.js
image

localhost換成elasticsearch的服務器地址,咸魚君部署的這臺是197.168.24.207。

image

換完之后,在elasticsearch-head目錄下,輸入如下命令,進入啟動目錄

cd node_modules/grunt/bin

使用如下命令啟動服務,使elasticsearch-head服務在后臺運行!

nohup ./grunt server &

最后,直接遠程通過瀏覽器訪問elasticsearch-head可視化管理界面,默認訪問地址是ip:9100,訪問結果如下!

image

至此,elasticsearch的安裝包括可視化界面插件elasticsearch-head已經完成了!

SpringBoot 整合 ElasticSearch

對于 SpringBoot 來說,ElasticSearch 其實只是一個中間件,用途在于提供高效的搜索服務,比較幸運的是 SpringBoot 也為我們提供了 ElasticSearch 依賴庫,添加依賴包,通過 JPA 訪問非常方便,整合過程如下!

創(chuàng)建一個SpringBoot項目

pom.xml中,添加依賴庫 ElasticSearch 依賴包

<!--jpa 支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--elasticsearch-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

application.properties中添加配置,其中節(jié)點名稱cluster-name需要與上面的配置保持一致!

spring.data.elasticsearch.cluster-name=my-es
spring.data.elasticsearch.cluster-nodes=197.168.24.207:9300

編寫 CURD

我們先寫一個的實體類Student,借助這個實體類來完成基礎的 CRUD 功能。

  • 新增實體類Student,其中indexName表示索引,type表示索引類別
@Data
@Accessors(chain = true)
@Document(indexName = "student", type = "school")
public class Student {

    private static final long serialVersionUID = 1l;

    @Id
    private String id;

    private String name;

    private String gender;

    private Integer age;
}

注意id字段是必須的,可以不寫注解@Id!

  • 使用 JPA 作為數據持久層,接口繼承自ElasticsearchRepository,同時新增兩個自定義查詢方法
public interface StudentRepository extends ElasticsearchRepository<Student, String> {

    /**
     * 通過姓名模擬查詢學生信息
     * @param keyword
     * @return
     */
    List<Student> findByNameLike(String keyword);

    /**
     * 自定義查詢,固定匹配查詢學生信息
     * @param keyword
     * @return
     */
    @Query("{\"match_phrase\":{\"name\":\"?0\"}}")
    List<Student> findByNameCustom(String keyword);
}
  • 創(chuàng)建控制層,編寫基礎的 CRUD 功能
@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * 批量添加
     * @param students
     * @return
     */
    @PostMapping("/batchAdd")
    public void add(@RequestBody List<Student> students){
        studentRepository.saveAll(students);
    }

    /**
     * 添加
     * @param student
     * @return
     */
    @PostMapping("/add")
    public void add(@RequestBody Student student){
        studentRepository.save(student);
    }

    /**
     * 修改
     * @param student
     * @return
     */
    @PostMapping("/update")
    public void updateById(@RequestBody Student student){
        studentRepository.save(student);
    }

    /**
     * 刪除
     * @param id
     * @return
     */
    @PostMapping("/delete/{id}")
    public void deleteById(@PathVariable String id){
        studentRepository.deleteById(id);
    }

    /**
     * 獲取所有信息
     * @return
     */
    @GetMapping("/get")
    public Object getAll(){
        Iterable<Student> iterable = studentRepository.findAll();
        List<Student> list = new ArrayList<>();
        iterable.forEach(list :: add);
        return list;
    }

    /**
     * 查詢指定ID
     * @param id
     * @return
     */
    @GetMapping("/get/{id}")
    public Object getById(@PathVariable String id){
        if(StringUtils.isEmpty(id)){
            return Result.error();
        }
        Optional<Student> studentOptional = studentRepository.findById(id);
        if(studentOptional.isPresent()){
            return studentOptional.get();
        }
        return null;
    }

    /**
     * 普通搜索
     * @param keyword
     * @return
     */
    @GetMapping("/search/name")
    public Object searchName(String keyword){
        List<Student> students = studentRepository.findByNameLike(keyword);
        return students;
    }

    /**
     * 自定義匹配
     * 普通搜索
     * @param keyword
     * @return
     */
    @GetMapping("/search/name/custom")
    public Object searchTitleCustom(String keyword){
        List<Student> students = studentRepository.findByNameCustom(keyword);
        return students;
    }

    /**
     * 高級搜索,可以自定義添加搜索字段
     * @param keyword
     * @return
     */
    @GetMapping("/top/search/name")
    public Object topSearchTitle(String keyword){
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryStringQuery(keyword))
                .build();
  //使用searchQuery進行搜索
        List<Student> students = elasticsearchTemplate.queryForList(searchQuery, Student.class);
        return students;
    }
}

CRUD 測試

CRUD 編寫完了,我們驗證一下是否可以正常操作,啟動 springboot 項目,使用 postman 進行測試。

  • 批量新增、新增功能測試
image
image

執(zhí)行之后,登錄可視化界面查詢界面,選擇索引student,可以很清晰的看到數據已經進去了

image
  • 修改功能測試,修改時需要傳入ID
image

王小賤從26歲修改為30歲,登錄可視化界面查詢數據也已經修改成功!

image
  • 刪除功能測試,只需要傳入ID
image

刪除李四,登錄可視化界面查詢數據也已經刪除成功!

image
  • 查詢功能測試,查詢所有數據
image
  • 查詢功能測試,查詢指定ID信息
image
  • 查詢功能測試,普通模糊查詢,ElasticSearch 會對關鍵詞進行拆分,只要有包含關鍵字的都會查詢出來,例如輸入王張,會將包含或者的姓名信息查詢出來
image
  • 查詢功能測試,高級查詢,這個是使用官方api提供的查詢入口,可以在方法中進行自定義搜索
image

總結

elasticsearch 在海量數據查詢方面,非常高效,本來想寫在大量數據查詢方面,數據庫與 elasticsearch 的查詢效率比對,由于篇幅較長會造成閱讀體驗降低,后在下篇文章中再次介紹這個部分。

對于想學習 elasticsearch 的新手,尤其是安裝部分可能比較困難,因此花的編寫時間比較多,后續(xù)的整合都比較簡單,elasticsearch 真正的強大的地方在于高效信息搜索,本篇對 elasticsearch 的搜索只是做一個基礎的介紹,具體的高級搜索方法大家可以參考官方文檔 API.

請關注我的訂閱號

訂閱號.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容