Elasticsearch快速入門和環境搭建

內容概述

本文內容主要集中在應用層,通過下面幾個部分介紹當前最流行的搜索工具: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官方倉庫拉取鏡像會很慢,所以在安裝完成後,需要在設置中將倉庫的地址替換為國內源,這裡推薦//docker.mirrors.ustc.edu.cn,速度很快,設置如下:

{
  "registry-mirrors": [
    "//docker.mirrors.ustc.edu.cn"
  ]
}

下面我們使用docker安裝Elasticsearchkibana鏡像,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實例,分別是elasticsearchkibana

在本地瀏覽器中,訪問//127.0.0.1:5601/,可以看到kibana的界面如下:

創建好的kibana已經默認添加了Elasticsearch的配置,通過管理工具可以很方便的查看ES集群的狀態,索引情況,刪除索引等。

kibana-monitor

下面通過dev tools創建索引,dev tools提供的命令提示很方便,並且可以把已寫好的請求保存在瀏覽器緩存中,非常適合用來學習Elasticsearch

create-index

這裡通過ES提供的RESTful Api創建了第一個索引, 並且設置了該索引中的mapping,ES的地址已經設置過,這裡可以不寫完整的域名,對應的curl完整請求如下:

curl --location --request PUT '//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,這些例子都是直接在kibanadev 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會被分詞為callaaaservice,所有包含這三個詞的文檔都會被搜索出來,例如下面:

//普通搜索,兩個文檔都會返回
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"
    }
  }
}

那如果條件是包含callaaaservice,但是不一定是連着的,該如何搜索呢?可以使用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。

以上內容屬個人學習總結,如有不當之處,歡迎在評論中指正