一到週末,就想在家裏躺屍,逛逛B站,看看直播,打打遊戲,美哉美哉。當然,作爲一名有自我修養的程序員,學習也是必不可少的。前段時間,我司的另一個項目組接手的項目中用到了elasticsearch,我就查了一下,原來是一個分佈式的搜索框架;所以,決定入門學習一下。
elasticsearch的背景
ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java語言開發的,並作爲Apache許可條款下的開放源碼發佈,是一種流行的企業級搜索引擎。ElasticSearch用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。官方客戶端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和許多其他語言中都是可用的。根據DB-Engines的排名顯示,Elasticsearch是最受歡迎的企業搜索引擎,其次是Apache Solr,也是基於Lucene。
上面就是百度百科的介紹,基本上就是和Solr同源,都是基於Lucene來進行的封裝。想了解更多資料的讀者,請自行百度。本篇着重講解elasticsearch的使用。
elasticsearch的安裝
至於安裝,這裏博主提供兩種方法。
一:使用Docker安裝:
博主以前使用Docker安裝過elasticsearch,所以讀者可以看博主之前的文章。
https://blog.csdn.net/qq_32101993/article/details/100021002
二:在windows上安裝:
因爲用於本地測試,開發,就直接在windows上就好了。
下載安裝
首先去官網下載壓縮包:https://www.elastic.co/cn/downloads/past-releases
ps:這裏的版本需要根據自己的實際情況選擇,因爲博主會使用SpringBoot封裝的方法操作elasticsearch,而maven提供的最新版的 spring-data-elasticsearch 是 3.2,與之對應的elasticsearch版本是6.4.3 ,但是elasticsearch的最新版是7.4.0,所以,爲了方便,博主直接選擇歷史版本。
各位讀者根據需求下載所需版本即可。
elasticsearch壓縮包下載完成,解壓就行了,然後在bin目錄下雙擊elasticsearch或者在doc命令中敲命令也行。
啓動成功如下圖所示:
將elasticsearch加入系統服務
如果每個服務都使用doc命令來啓動,那麼電腦底下的任務欄會很亂,如果不小心關錯了,又要重新啓動一次,甚至需要殺掉進程,再次啓動。所以,直接將其添加爲系統服務,通過後臺服務的方式來啓動。
在bin目錄下的doc命令行中執行下面的命令
elasticsearch-service.bat install elasticsearch-6.4.3 # 最後是服務的名字,這裏可以自定義
執行上面的命令,當前服務就添加進了系統。然後可以通過任務管理器啓動了。
ps:通過任務管理器啓動elasticsearch服務,若是每次都顯示已停止,就證明此刻服務時有問題的。
需要對服務進行配置,在bin目錄下的doc命令行中輸入以下命令
elasticsearch-service.bat manager elasticsearch-6.4.3 # 後面跟的就是剛纔設置的服務名稱
然後,就會彈出一個管理界面。
根據圖上所示,之前是一個Java虛擬機的地址,現在選擇Use default,使用默認的,點擊確定。再次啓動服務,就可以看到服務啓動成功了。
通過PostMan工具,訪問地址:http://localhost:9200
看到了返回結果,當然,有讀者會問,爲什麼自己的name和cluster_name不一樣呢?這是因爲博主在啓動之前,對elasticsearch的默認配置進行了更改。
修改配置文件
# 集羣名稱
cluster.name: qfcwx
# 節點名稱
node.name: node-9006
# 配置是否跨域,方便head插件操作
http.cors.enabled: true
http.cors.allow-origin: "*"
博主就修改了上面的配置,其實還有很多配置,只是現在沒有接觸到。然後重啓服務,就可以看到自定義的集羣名稱和節點名稱了。
上面這些內容都是在說elasticsearch的安裝與啓動,下面就進行SpringBoot操作elasticsearch的環節。
SpringBoot整合elasticsearch
①、導入相應的約束。
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
這裏使用的是maven倉庫提供的最新版,依賴下載完,讀者可以點開依賴,查看elasticsearch的版本。因爲使用SpringBoot,所以其他包就不貼出來了,讀者根據項目需求導入。
②、修改配置文件
spring:
data:
elasticsearch:
cluster-nodes: 127.0.0.1:9300
cluster-name: qfcwx
③、編碼實戰
這裏就以檢索文章爲例,建立一個實體類。
package com.qfcwx.micro.search.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import java.io.Serializable;
/**
* @ClassName: Article
* @Author: 清風一陣吹我心
* @Description: TODO Elasticsearch需要的對象
* @Date: 2019/10/19 16:11
* @Version 1.0
**/
@Data
@Document(indexName = "qfcwx_article", type = "article")
public class Article implements Serializable {
@Id
private String id;
/**
* 是否索引,看該域是否能被搜索
* 是否分詞,表示搜索的時候是整體匹配還是單詞匹配
* 是否存儲,是否在頁面上顯示
*/
@Field(index = true, analyzer = "chinese", searchAnalyzer = "chinese")
private String title;
@Field(index = true, analyzer = "chinese", searchAnalyzer = "chinese")
private String content;
/**
* 審批狀態
*/
private String state;
}
@Data是lombook的註解,自動生成setter、getter等方法。
@Document這是elasticsearch的註解,indexName是索引的名字;type是類型。
@Field這個註解上面,類中也有相應的註解,表明當前屬性需要索引、分詞,存儲。
先說一下elasticsearch和MySQL的對應關係:
elasticsearch | MySQL |
---|---|
索引 | 數據庫 |
類型 | 表 |
文檔 | 行 |
上面說的分詞,文章後面部分會做相應的說明。
實體類創建完畢,接着創建dao層。因爲使用spring-data的緣故,它將所有的關係型數據庫與非關係型數據庫的操作都封裝起來,提供一個統一的增刪改查方法,如果不通過配置和代碼,無法區分當前操作的是什麼數據庫。用的時間長了,感覺整個人都有點廢了的感覺,但是對於敏捷開發,真的是非常方便的。
public interface SearchRepository extends ElasticsearchRepository<Article, String> {
/**
* 自定義分頁查詢方法
*/
Page<Article> findByTitleOrContentLike(String title, String content, Pageable pageable);
}
這裏寫了一個自定義方法,就像寫JPA一樣,根據方法名就能自動生成相應的查詢條件,不需要自己去寫sql。
然後寫service層。
@Service
@Transactional(rollbackFor = Exception.class)
public class SearchService {
@Autowired
private SearchRepository searchRepository;
public void save(Article article) {
article.setId(NumberUtil.getBitRandomNumber(6));
searchRepository.save(article);
}
public PageResult<Article> findByKey(String key, Integer page, Integer size) {
Pageable pageable = PageRequest.of(page - 1, size);
Page<Article> pageList = searchRepository.findByTitleOrContentLike(key, key, pageable);
return new PageResult<Article>(pageList.getTotalElements(), pageList.getContent());
}
}
這裏提供了兩個方法,一個是新增,一個是分頁查詢。
最後就是控制層了。
@RestController
@RequestMapping("/api/v1.0/article")
public class SearchController {
@Autowired
private SearchService searchService;
@PostMapping
public ResultBean<Boolean> save(@RequestBody Article article) {
searchService.save(article);
return new ResultBean<>(Boolean.TRUE);
}
@GetMapping(value = "/{key}/{page}/{size}")
public ResultBean<PageResult<Article>> findByKey(@PathVariable String key, @PathVariable Integer page, @PathVariable Integer size) {
return new ResultBean<>(searchService.findByKey(key, page, size));
}
}
使用SpringBoot操作elasticsearch就是這麼簡單。
啓動項目,使用Postman工具進行測試。
可以看到返回結果,成功的插入了數據,接着多插入幾條數據。如何查看是否將數據存入了索引庫呢?此時,就可以使用第二個查詢接口了。
第一個參數是key,也就是通過什麼詞來搜索,後面兩個對應頁數和每頁的個數。
elasticsearch分詞器
通過上文知道了,操作elasticsearch是這麼簡單。SpringBoot大大簡化了操作關係型數據庫和非關係型數據庫的難度。但是,在開發中,還是有很多坑需要自己慢慢去踩,去解決的。
上面的Article實體類中說到了@Field這個註解,其中提到了分詞。那麼什麼是分詞呢?
其實理解起來很簡單。就是一句話分成幾個詞。下面就進行分詞的操作。
使用了elasticsearch原生的分詞器。
在Postman中輸入以下命令:
# elasticsearch 6.x和7.x
http://localhost:9200/_analyze/?pretty=true 並傳入json格式的數據:{ "analyzer": "chinese", "text": "我是程序員" }
# elasticsearch 5.x及以下
http://localhost:9200/_analyze?analyzer=chinese&pretty=true&text=我是程序員
結果反饋了,elasticsearch的默認分詞器,對中文並不友好。明明可以分成 我是、我、程序員等詞彙,連最基本的程序員詞彙都沒分出來,這真的是扎程序員的心啊。所以,爲了解決這種問題,就需要使用能夠支持中文的分詞器——ik分詞器。
至於ik分詞器是什麼,請各位自行查閱相關資料。
首先下載這個插件,和elasticsearch的版本對應。下載地址:
https://github.com/medcl/elasticsearch-analysis-ik/releases
下載完了,解壓放入elasticsearch文件夾裏面的plugin文件夾中即可。然後重啓服務。
修改analyzer的參數,重新發送請求。
ik_smart: 會將文本做最粗粒度的拆分,比如會將“我是程序員”,拆分爲:我、是、程序員。
ik_max_word: 會將文本做最細粒度的拆分,比如會將“我是程序員”,拆分爲:我、是、程序員、程序、員。
上面兩種分詞器,讀者根據開發需求選擇一個就可以了。
除了這些正規詞彙,還有一些詞,使用ik分詞器,也是無法正確分詞的。比如,博主經常在B站中看番。對於B站的粉絲肯定知道"阿偉死了"這個詞吧!如果使用這個詞來測試,會是什麼樣的結果呢?就來測試一下:
上面的分詞器還是將每個字分開了。這樣通過索引也無法找到正確的內容。那麼如何解決這個問題呢?“解鈴還須繫鈴人”,ik分詞器提供了自定義分詞策略。
進入我們剛纔解壓放入elasticsearch的plugin文件夾下的ik分詞器目錄,在config目錄中可以看到很多以.dic爲後綴的文件。
這些都是ik分詞器自帶的單詞與解釋的文件。以同樣的方式創建一個.dic的文件,名稱根據自己的喜好命名。然後用記事本打開,在裏面填入需要分詞的詞語。注意,這裏雖然創建了文件,但是分詞器並不知道自定義文件的名稱是什麼,所以,需要在 IKAnalyzer.cfg.xml文件中進行配置。
根據上面的提示,填入文件名稱及後綴就行,然後重啓服務,再用Postman測試。
通過圖片,可以看到,自定義的詞彙成功分詞了。如果以後還有其他分詞器沒有收錄的詞語,將其添加到文件中即可。關於ik分詞器的講解,到這裏就結束了。
Logstash同步數據
Logstash是一個開源的服務器端數據處理管道,可以同時從多個數據源獲取數據,並對其進行轉換,然後將其發送到你最喜歡的“存儲”。(當然,我們最喜歡的是Elasticsearch)
通過上面的話,可以知道Logstash可以將不同數據庫的數據同步到elasticsearch中。在實際開發中,不可能通過手動添加的方式將數據插入索引庫,所以需要藉助第三方工具,將數據庫的數據同步到索引庫。此時,Logstash出現了,它的使用方法也很簡單,下面講解一下,它是如何使用的。
首先下載對應版本的Logstash包,可以通過上面提供下載elasticsearch的地址進行下載,完成後解壓。
因爲解壓完的目錄和elasticsearch與MySQL沒有絲毫聯繫,這時就需要我們編寫配置文件了。根據官網和網上提供的配置文件,將其進行修改。其實就像Java連接數據庫,需要指明驅動、用戶名、密碼;操作elasticsearch,需要指明地址、集羣名稱等。這裏就是將elasticsearch與MySQ聯繫起來。熟悉JDBC操作的讀者,肯定知道這些配置如何填寫,這裏就不細說了。
先看一下上面配置中數據庫中的數據。
數據庫目前就添加了兩條測試數據。然後查看elasticsearch中索引庫中的文檔。
通過外部命令查看當前索引庫中的數據:
http://localhost:9200/qfcwx_article/article/_search
此時,索引庫中只有兩條數據,接下來就使用Logstash往索引庫中添加數據。
在Logstash的bin目錄下輸入命令:
logstash -f ../mysql/mysql.conf # 後面跟的是文件地址,這是填的相對路徑
命令敲完,等一會就會看到紅色畫線部分提示啓動成功。因爲在配置文件中配置的同步時間是每分鐘同步一次,所以就等服務啓動完成之後的一分鐘後查看doc命令行的日誌輸出。
紅框部分顯示了配置文件中配置的sql,還有執行完的結果集。這時,再看看索引庫中的所有數據。
查詢結果表明,數據同步成功。
Logstash的基本用法就講完了。
elasticsearch-head插件的使用
在Docker安裝elasticsearch那篇博文中,已經提到了使用head插件來操作elasticsearch,所以這篇文章就簡短的提一下。
head插件是一個用來操作elasticsearch的圖形化界面工具,需要先下載,然後解壓啓動。但是Google提供了一款插件,和我們所要使用的插件是一模一樣的,只需在Google商店搜索並安裝即可。省去了在本地安裝下載的麻煩。
一切準備就緒就可以啓動elasticsearch服務,然後打開head插件進行連接了。
點擊菜單欄上的“索引”,可以新建索引。
保存,然後在數據瀏覽中可以看到索引中是否有數據。因爲剛建立索引,所以索引庫中還沒有數據。
接着就通過這個插件來添加幾條數據。
如上圖所示,右邊提示created就表明創建成功了。然後在查看索引庫中的數據。
此時就將剛纔添加的數據顯示出來了,如果數據看不完整,請刷新整個頁面。
當然,也能對已經存在的數據進行刪除。只需要根據數據的id進行下面的操作即可。
本篇關於elasticsearch的文章到這裏就接近尾聲了,上面提到的所有知識點,都只是一個入門,要想深入,還需要通過資料以及官方文檔進行學習。當然,如果文章中出現不足或者錯誤的地方也請各位讀者指出。程序員就是這樣一個特殊的羣體,讓學習永不止步。希望與各位讀者共同進步。
只有明白了人性的弱點,纔能有針對性的改變自己,適應環境,才能掌控自己的人生。