這篇實(shí)戰(zhàn)攻略,帶你輕松入門Elasticsearch

內(nèi)容概述

本文內(nèi)容主要集中在應(yīng)用層,通過下面幾個(gè)部分介紹當(dāng)前最流行的搜索工具:Elasticsearch,了解這些內(nèi)容后,可以快速開始使用它。

  • 什么是Elasticsearch,為什么要使用它?
  • 基礎(chǔ)概念:節(jié)點(diǎn),索引,類型映射和文檔
  • 本地環(huán)境搭建,創(chuàng)建第一個(gè)index
  • 常用RESTful Api示例

什么是Elasticsearch,為什么要使用它?

Elasticsearch 是一個(gè)分布式、RESTful 風(fēng)格的搜索和數(shù)據(jù)分析引擎。

它基于Lunece實(shí)現(xiàn),使用java語言編寫。Lunece是一個(gè)優(yōu)秀的搜索引擎庫,但它使用起來非常復(fù)雜。

Elasticsearch通過對(duì) Lunece的封裝,隱藏了復(fù)雜性,提供了使用簡單的RESTful Api。

同時(shí)也實(shí)現(xiàn)了分布式集群特性,具有存儲(chǔ)數(shù)據(jù)大,查詢性能好,擴(kuò)展方便等特點(diǎn)。

為什么要使用它

在業(yè)務(wù)開發(fā)中,基于ES的特性,通常有下面這些場景需要使用它:

  • 存儲(chǔ)大量數(shù)據(jù)。通過在使用mysql存儲(chǔ)的時(shí)候,數(shù)據(jù)的單位是G。使用ES的時(shí)候,數(shù)據(jù)的單位是T。由此可以看出ES使用于大數(shù)據(jù)量的存儲(chǔ)場景,基于分布式特性,它也支持備份和容災(zāi),并且可以很容易水平擴(kuò)展容量。
  • 分詞搜索引擎。ES具有強(qiáng)大的分詞能力,可以支持高性能的實(shí)時(shí)搜索。
  • 高效數(shù)據(jù)分析。ES提供的聚合分析功能,可實(shí)現(xiàn)對(duì)保存的大量數(shù)據(jù)的近實(shí)時(shí)統(tǒng)計(jì)分析。

基礎(chǔ)概念簡介

要使用ES,需要了解幾個(gè)最基本的概念,節(jié)點(diǎn)(node),索引(index),類型映射(mapping)和文檔(doc)。

節(jié)點(diǎn)(node)

節(jié)點(diǎn)是組成ES集群的基本單位,每個(gè)節(jié)點(diǎn)是一個(gè)運(yùn)行的ES實(shí)例。每個(gè)物理機(jī)器上可以有多個(gè)節(jié)點(diǎn),使用不同的端口和節(jié)點(diǎn)名稱。

節(jié)點(diǎn)按主要功能可以分為三種:主節(jié)點(diǎn)(Master Node),協(xié)調(diào)節(jié)點(diǎn)(Coordianting Node)和數(shù)據(jù)節(jié)點(diǎn)(Data Node)。下面簡單介紹下:

  • 主節(jié)點(diǎn):處理創(chuàng)建,刪除索引等請(qǐng)求,維護(hù)集群狀態(tài)信息。可以設(shè)置一個(gè)節(jié)點(diǎn)不承擔(dān)主節(jié)點(diǎn)角色
  • 協(xié)調(diào)節(jié)點(diǎn):負(fù)責(zé)處理請(qǐng)求。默認(rèn)情況下,每個(gè)節(jié)點(diǎn)都可以是協(xié)調(diào)節(jié)點(diǎn)。
  • 數(shù)據(jù)節(jié)點(diǎn):用來保存數(shù)據(jù)??梢栽O(shè)置一個(gè)節(jié)點(diǎn)不承擔(dān)數(shù)據(jù)節(jié)點(diǎn)角色

索引(index)

索引是ES中的邏輯概念,是文檔的容器。對(duì)ES的操作,基本都是對(duì)索引操作,一個(gè)ES集群中,可以創(chuàng)建多個(gè)索引。

索引定義了一組文檔的數(shù)據(jù)模型和處理方法。每個(gè)索引可以有多個(gè)主分片和副本分片,分別保存在不同的節(jié)點(diǎn)。

  • 主分片的作用是對(duì)索引的擴(kuò)容,使一個(gè)索引的容量可以突破單機(jī)的限制。
  • 副本分片是對(duì)數(shù)據(jù)的保護(hù),每個(gè)主分片對(duì)應(yīng)一個(gè)或多個(gè)副本分片,當(dāng)主分片所在節(jié)點(diǎn)宕機(jī)時(shí),副本分片會(huì)被提升為對(duì)應(yīng)的主分片使用。
  • 一個(gè)主分片和它的副本分片,不會(huì)分配到同一個(gè)節(jié)點(diǎn)上。
  • 一個(gè)索引的分片數(shù)在創(chuàng)建時(shí)指定,如果要修改需要重建索引,代價(jià)很高。

類型映射(mapping)

mapping定義了一個(gè)索引中,文檔保存的每個(gè)字段的數(shù)據(jù)類型。根據(jù)數(shù)據(jù)類型的不同,在添加文檔時(shí)對(duì)每個(gè)字段的處理也不同。

例如,對(duì)text類型的字段,會(huì)先使用分詞器分詞,生成倒排索引,用于之后的搜索。對(duì)keyword類型的字段,不會(huì)分詞,搜索時(shí)只能精確查找。

一個(gè)簡單的mapping示例如下:

{
    "javalogs": { //索引名稱
        "mappings": {
            "properties": {
                "log_content": { //text類型,分詞,用于之后的分詞索引
                    "type": "text"
                },
                "date": {//時(shí)間類型
                    "type": "date" 
                },
                "log_level": { //keyword類型,不分詞
                    "type": "keyword" 
                },
                "ip": {
                    "type": "keyword"
                }
            }
        }
    }
}

在6.x版本中,每個(gè)索引中還可以有多個(gè)type,區(qū)分不同的mapping。在7.x中,type被取消,每個(gè)索引只有一個(gè)type:_doc

文檔(doc)

  • 文檔是Elasticsearch中的最小單位,每個(gè)索引都是有數(shù)量眾多的文檔組成的。

  • 文檔中包含多個(gè)字段,每個(gè)字段的類型由mapping定義。

  • 在一個(gè)索引中每個(gè)文檔都有一個(gè)唯一id,可以在添加時(shí)指定,也可以自動(dòng)生成。

下面通過一張圖來描述,節(jié)點(diǎn)(node),索引(index)和文檔(doc)之間的關(guān)系。

image

本地環(huán)境搭建,創(chuàng)建第一個(gè)index

一切知識(shí)都要通過實(shí)踐掌握,所以在了解基本的概念和邏輯后,下面就進(jìn)入實(shí)踐環(huán)節(jié)。

這里推薦使用docker來搭建本地開發(fā)環(huán)境,docker對(duì)應(yīng)windows和mac系統(tǒng)都有桌面版本,使用非常方便。因?yàn)榫W(wǎng)絡(luò)限制,直接使用docker官方倉庫拉取鏡像會(huì)很慢,所以在安裝完成后,需要在設(shè)置中將倉庫的地址替換為國內(nèi)源,這里推薦https://docker.mirrors.ustc.edu.cn,速度很快,設(shè)置如下:

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

下面我們使用docker安裝Elasticsearchkibana鏡像,kibana是es官方配套的可視化分析工具,使用它的頁面dev tools可以很方便的通過api操作es。

因?yàn)橐瑫r(shí)部署兩個(gè)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 #節(jié)點(diǎn)名稱
      - bootstrap.memory_lock=true
      - network.publish_host=elasticsearch #節(jié)點(diǎn)發(fā)布的網(wǎng)絡(luò)名稱
      - discovery.seed_hosts=es-simple #設(shè)置集群中的主機(jī)地址
      - cluster.initial_master_nodes=es-simple #手動(dòng)設(shè)置可以成為master的節(jié)點(diǎn)集合
    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

創(chuàng)建一個(gè)名稱為docker-compose.yaml文件,復(fù)制下面的配置到文件中,然后再文件所在目錄執(zhí)行docker-compose up,之后會(huì)啟動(dòng)兩個(gè)docker實(shí)例,分別是elasticsearchkibana。

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

image

創(chuàng)建好的kibana已經(jīng)默認(rèn)添加了Elasticsearch的配置,通過管理工具可以很方便的查看ES集群的狀態(tài),索引情況,刪除索引等。

kibana-monitor

下面通過dev tools創(chuàng)建索引,dev tools提供的命令提示很方便,并且可以把已寫好的請(qǐng)求保存在瀏覽器緩存中,非常適合用來學(xué)習(xí)Elasticsearch

create-index

這里通過ES提供的RESTful Api創(chuàng)建了第一個(gè)索引, 并且設(shè)置了該索引中的mapping,ES的地址已經(jīng)設(shè)置過,這里可以不寫完整的域名,對(duì)應(yīng)的curl完整請(qǐng)求如下:

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,這些例子都是直接在kibanadev tools中運(yùn)行的,如果想用curl訪問,可參考前一節(jié)中的轉(zhuǎn)換例子。

新增文檔

//自動(dòng)生成_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在文檔查詢時(shí),對(duì)于不分詞的查詢,直接按值查詢即可,例如下面這樣:

//不分詞類型查詢
POST javalogs/_search
{
  "query": {
    "match": {
      "ip": "10.223.32.67"
    }
  }
}

查詢文檔-分詞類型

這里主要說下分詞類型的查詢,對(duì)于分析類型的field在查詢時(shí),也會(huì)默認(rèn)把查詢的語句分詞。假設(shè)有兩個(gè)文檔如下:

//文檔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"
}

當(dāng)搜索條件為call aaa service時(shí),實(shí)際上會(huì)把兩個(gè)文檔都搜索出來。
這是因?yàn)樵谒阉鲿r(shí),條件call aaa service會(huì)被分詞為call,aaaservice,所有包含這三個(gè)詞的文檔都會(huì)被搜索出來,例如下面:

//普通搜索,兩個(gè)文檔都會(huì)返回
POST javalogs/_search
{
  "query": {
    "match": {
      "log_content": "call aaa service"
    }
  }
}

那如果想要只搜索包含call aaa service的文檔,應(yīng)該如何做呢?

按照上面的分析,需要同時(shí)包含這三個(gè)詞,并且按照給定的順序,才返回對(duì)應(yīng)的文檔,那么這個(gè)可以使用match_phrase實(shí)現(xiàn),示例如下:

//文檔必須同時(shí)包含三個(gè)詞,并且順序與搜索條件一致才會(huì)返回。這里只會(huì)返回-文檔1
POST javalogs/_search
{
  "profile": "true", 
  "query": {
    "match_phrase": {
      "log_content": "call aaa service"
    }
  }
}

那如果條件是包含call,aaaservice,但是不一定是連著的,該如何搜索呢?可以使用operator操作符實(shí)現(xiàn)。

例如有第三個(gè)文檔如下:

//文檔3
{
  "log_content" : "call inner aaa service error",
  "date" : "2020-04-15T11:09:08",
  "log_level": "error",
  "ip": "10.223.32.67"
}

要想把文檔1文檔2都搜索出來,查詢的示例如下:

//文檔中同時(shí)包含call,aaa和service就會(huì)返回,不按順序。會(huì)返回-文檔1和文檔2
POST javalogs/_search
{
  "query": {
    "match": {
      "log_content": 
      {
        "query": "call aaa service",
        "operator": "and"
      }
    }
  }
}

上面就是對(duì)Elasticsearch的簡單介紹和實(shí)戰(zhàn)操作示例,希望能幫助大家快速入門使用ES。

以上內(nèi)容屬個(gè)人學(xué)習(xí)總結(jié),如有不當(dāng)之處,歡迎在評(píng)論中指正

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容