內容概述
本文內容主要集中在應用層,通過下面幾個部分介紹當前最流行的搜尋工具:Elasticsearch
,瞭解這些內容後,可以快速開始使用它。
- 什麼是
Elasticsearch
,為什麼要使用它? - 基礎概念:節點,索引,型別對映和文件
- 本地環境搭建,建立第一個
index
- 常用
RESTful Api
示例
什麼是Elasticsearch
,為什麼要使用它?
Elasticsearch
是一個分散式、RESTful 風格的搜尋和資料分析引擎。
它基於Lunece
實現,使用java
語言編寫。Lunece
是一個優秀的搜尋引擎庫,但它使用起來非常複雜。
Elasticsearch
通過對 Lunece
的封裝,隱藏了複雜性,提供了使用簡單的RESTful Api。
同時也實現了分散式叢集特性,具有儲存資料大,查詢效能好,擴充套件方便等特點。
為什麼要使用它
在業務開發中,基於ES的特性,通常有下面這些場景需要使用它:
- 儲存大量資料。通過在使用mysql儲存的時候,資料的單位是
G
。使用ES的時候,資料的單位是T
。由此可以看出ES使用於大資料量的儲存場景,基於分散式特性,它也支援備份和容災,並且可以很容易水平擴充套件容量。 - 分詞搜尋引擎。ES具有強大的分詞能力,可以支援高效能的實時搜尋。
- 高效資料分析。ES提供的聚合分析功能,可實現對儲存的大量資料的近實時統計分析。
基礎概念簡介
要使用ES,需要了解幾個最基本的概念,節點(node
),索引(index
),型別對映(mapping
)和文件(doc
)。
節點(node
)
節點是組成ES叢集的基本單位,每個節點是一個執行的ES例項。每個物理機器上可以有多個節點,使用不同的埠和節點名稱。
節點按主要功能可以分為三種:主節點(Master Node),協調節點(Coordianting Node)和資料節點(Data Node)。下面簡單介紹下:
- 主節點:處理建立,刪除索引等請求,維護叢集狀態資訊。可以設定一個節點不承擔主節點角色
- 協調節點:負責處理請求。預設情況下,每個節點都可以是協調節點。
- 資料節點:用來儲存資料。可以設定一個節點不承擔資料節點角色
索引(index
)
索引是ES中的邏輯概念,是文件的容器。對ES的操作,基本都是對索引操作,一個ES叢集中,可以建立多個索引。
索引定義了一組文件的資料模型和處理方法。每個索引可以有多個主分片和副本分片,分別儲存在不同的節點。
- 主分片的作用是對索引的擴容,使一個索引的容量可以突破單機的限制。
- 副本分片是對資料的保護,每個主分片對應一個或多個副本分片,當主分片所在節點當機時,副本分片會被提升為對應的主分片使用。
- 一個主分片和它的副本分片,不會分配到同一個節點上。
- 一個索引的分片數在建立時指定,如果要修改需要重建索引,代價很高。
型別對映(mapping
)
mapping
定義了一個索引中,文件儲存的每個欄位的資料型別。根據資料型別的不同,在新增文件時對每個欄位的處理也不同。
例如,對text型別的欄位,會先使用分詞器分詞,生成倒排索引,用於之後的搜尋。對keyword型別的欄位,不會分詞,搜尋時只能精確查詢。
一個簡單的mapping示例如下:
{
"javalogs": { //索引名稱
"mappings": {
"properties": {
"log_content": { //text型別,分詞,用於之後的分詞索引
"type": "text"
},
"date": {//時間型別
"type": "date"
},
"log_level": { //keyword型別,不分詞
"type": "keyword"
},
"ip": {
"type": "keyword"
}
}
}
}
}
在6.x版本中,每個索引中還可以有多個type,區分不同的mapping。在7.x中,type被取消,每個索引只有一個type:_doc
文件(doc
)
-
文件是
Elasticsearch
中的最小單位,每個索引都是有數量眾多的文件組成的。 -
文件中包含多個欄位,每個欄位的型別由
mapping
定義。 -
在一個索引中每個文件都有一個唯一id,可以在新增時指定,也可以自動生成。
下面通過一張圖來描述,節點(node
),索引(index
)和文件(doc
)之間的關係。
本地環境搭建,建立第一個index
一切知識都要通過實踐掌握,所以在瞭解基本的概念和邏輯後,下面就進入實踐環節。
這裡推薦使用docker來搭建本地開發環境,docker對應windows和mac系統都有桌面版本,使用非常方便。因為網路限制,直接使用docker官方倉庫拉取映象會很慢,所以在安裝完成後,需要在設定中將倉庫的地址替換為國內源,這裡推薦https://docker.mirrors.ustc.edu.cn
,速度很快,設定如下:
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn"
]
}
下面我們使用docker安裝Elasticsearch
和kibana
映象,kibana
是es官方配套的視覺化分析工具,使用它的頁面dev tools可以很方便的通過api操作es。
因為要同時部署兩個docker映象,這裡推薦使用docker-composer
,桌面版安裝完成後就帶有該命令,需要的配置如下:
services:
kibana:
image: kibana:7.2.0
container_name: kibana-simple
environment:
- TIMELION_ENABLED=true
ports:
- "5601:5601"
networks:
- mynetwork
elasticsearch:
image: elasticsearch:7.2.0
container_name: es-simple
environment:
- cluster.name=mytestes #這裡就是ES叢集的名稱
- node.name=es-simple #節點名稱
- bootstrap.memory_lock=true
- network.publish_host=elasticsearch #節點發布的網路名稱
- discovery.seed_hosts=es-simple #設定叢集中的主機地址
- cluster.initial_master_nodes=es-simple #手動設定可以成為master的節點集合
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata1:/usr/local/elasticsearch/simpledata
ports:
- 9200:9200
networks:
- mynetwork
volumes:
esdata1:
driver: local
networks:
mynetwork:
driver: bridge
建立一個名稱為docker-compose.yaml
檔案,複製下面的配置到檔案中,然後再檔案所在目錄執行docker-compose up
,之後會啟動兩個docker例項,分別是elasticsearch
和kibana
。
在本地瀏覽器中,訪問http://127.0.0.1:5601/
,可以看到kibana
的介面如下:
建立好的kibana
已經預設新增了Elasticsearch
的配置,通過管理工具可以很方便的檢視ES叢集的狀態,索引情況,刪除索引等。
下面通過dev tools
建立索引,dev tools
提供的命令提示很方便,並且可以把已寫好的請求儲存在瀏覽器快取中,非常適合用來學習Elasticsearch
。
這裡通過ES提供的RESTful Api
建立了第一個索引, 並且設定了該索引中的mapping
,ES的地址已經設定過,這裡可以不寫完整的域名,對應的curl完整請求如下:
curl --location --request PUT 'http://127.0.0.1:9200/javalogs' \
--header 'Content-Type: application/json' \
--data-raw '{
"mappings": {
"properties": {
"log_content": {
"type": "text"
},
"date": {
"type": "date"
},
"log_level": {
"type": "keyword"
},
"ip": {
"type": "keyword"
}
}
}
}'
常用RESTful Api
示例
下面介紹下Elasticsearch
中常用的api,這些例子都是直接在kibana
的dev tools
中執行的,如果想用curl訪問,可參考前一節中的轉換例子。
新增文件
//自動生成_id
POST javalogs/_doc
{
"log_content" : "get user_id 123456",
"date" : "2020-04-15T11:09:08",
"log_level": "info",
"ip": "10.223.32.67"
}
//指定_id
POST javalogs/_doc/111
{
"log_content" : "api response in 55ms",
"date" : "2020-04-15T11:09:07",
"log_level": "info",
"ip": "10.223.32.67"
}
查詢文件-不分詞型別
ES在文件查詢時,對於不分詞的查詢,直接按值查詢即可,例如下面這樣:
//不分詞型別查詢
POST javalogs/_search
{
"query": {
"match": {
"ip": "10.223.32.67"
}
}
}
查詢文件-分詞型別
這裡主要說下分詞型別的查詢,對於分析型別的field
在查詢時,也會預設把查詢的語句分詞。假設有兩個文件如下:
//文件1
{
"log_content" : "call aaa service error",
"date" : "2020-04-15T11:09:07",
"log_level": "error",
"ip": "10.223.32.67"
}
//文件2
{
"log_content" : "call bbb service error",
"date" : "2020-04-15T11:09:08",
"log_level": "error",
"ip": "10.223.32.67"
}
當搜尋條件為call aaa service
時,實際上會把兩個文件都搜尋出來。
這是因為在搜尋時,條件call aaa service
會被分詞為call
,aaa
和service
,所有包含這三個詞的文件都會被搜尋出來,例如下面:
//普通搜尋,兩個文件都會返回
POST javalogs/_search
{
"query": {
"match": {
"log_content": "call aaa service"
}
}
}
那如果想要只搜尋包含call aaa service
的文件,應該如何做呢?
按照上面的分析,需要同時包含這三個詞,並且按照給定的順序,才返回對應的文件,那麼這個可以使用match_phrase
實現,示例如下:
//文件必須同時包含三個詞,並且順序與搜尋條件一致才會返回。這裡只會返回-文件1
POST javalogs/_search
{
"profile": "true",
"query": {
"match_phrase": {
"log_content": "call aaa service"
}
}
}
那如果條件是包含call
,aaa
和service
,但是不一定是連著的,該如何搜尋呢?可以使用operator
操作符實現。
例如有第三個文件如下:
//文件3
{
"log_content" : "call inner aaa service error",
"date" : "2020-04-15T11:09:08",
"log_level": "error",
"ip": "10.223.32.67"
}
要想把文件1
和文件2
都搜尋出來,查詢的示例如下:
//文件中同時包含call,aaa和service就會返回,不按順序。會返回-文件1和文件2
POST javalogs/_search
{
"query": {
"match": {
"log_content":
{
"query": "call aaa service",
"operator": "and"
}
}
}
}
上面就是對Elasticsearch
的簡單介紹和實戰操作示例,希望能幫助大家快速入門使用ES。
以上內容屬個人學習總結,如有不當之處,歡迎在評論中指正