Elasticsearch簡介、倒排索引、文檔基本操做、分詞器

lucene、Solr、Elasticsearchhtml

一、倒排序索引java

二、Lucene是類庫node

三、solr基於lucenelinux

四、ES基於lucenegit

1、Elasticsearch 核心術語

特色:
一、es能夠支持空格查詢,多個關鍵字

二、空格支持

三、拆詞查詢

四、搜索內容能夠高亮

五、海量數據查庫
ES 能夠對照着 數據庫 來理解:
  • 索引index    -------->    表
  • 文檔 document    -------->    行(記錄)
  • 字段 fields    -------->    列
Elasticsearch的存儲形式:
stu_index
{
id: 1001,
name: jason,
age: 19
},
{
id: 1002,
name: tom,
age: 18
},
{
id: 1003,
name: rose,
age: 22
}
集羣相關
  • 分片(shard):把索引庫拆分爲多份,分別放在不一樣的節點上,好比有3個節點,3個節點的全部數據內容加在一塊兒是一個完整的索引庫。分別保存到三個節點上,目的爲了水平擴展,提升吞吐量。
  • 備份(replica):每一個shard的備份。
簡稱

shard = primary shard(主分片)
replica = replica shard(備份節點)github

2、ES集羣架構原理

加入有3TB的數據那麼ES向上面的架構模型,每一個shard會承擔1TB的數據,當一個ES的shard出現故障,那麼它的replica就會成爲它的角色。redis

shard和replica機制   

A、index包含多個shard   數據庫

B、每一個shard都是一個最小工做單元,承載部分數據,lucene實例,完整地創建索引和處理請求的能力  json

C、增長或減小節點時,shard會自動地在node中負載均衡   vim

D、primary shard和replica shard,每一個document確定只存在於某一個primary shard以及其對應的replica shard 中,不可能存在於多個primary shard   

E、replica shard是primary shard 的副本,負責容錯以及承擔讀請求負載   

F、primary shard的數量在建立索引的時候就固定了,replica shard的數量能夠隨時修改   

G、primary shard不能和本身的replica shard放在同一節點上,可是能夠和其它primary shard放在同一節點上

3、倒排索引

ES爲何這麼快?

        一、索引方式的區別,es主要是利用倒排索引(inverted index),這個翻譯可能會讓初次接觸的人產生誤解,誤覺得是倒着排序?其實不是這樣,通常關係型數據庫索引是把某個字段創建起一張索引表,傳入這個字段的某個值,再去索引中判斷是否有這個值,從而找到這個值所在數據(id)的位置。而倒排索引則是把這個值所在的文檔id記錄下來,當輸入這個值的時候,直接查詢出這個值所匹配的文檔id,再取出id。因此咱們在創建es索引的時候,有分詞的概念,至關於能夠把filed字段內容拆分,而後索引記錄下來。例如「我愛中國」,能夠拆分紅「我」,「愛」,「中國」,「我愛中國」這五個詞,同時記錄下來這幾個關鍵詞的對應文檔數據id是1,當咱們查詢「我」,「中國」時,都能查出這條數據。而若是使用關係型數據庫去查包含「中國」這個關鍵字的數據的時候,則須要like先後通配全表掃描,沒法快速找到關鍵詞所在的數據行。

        二、倒排索引是不可更改的,一旦它被創建了,裏面的數據就不會再進行更改。這樣作就帶來了如下幾個好處:

  •  不用給索引加鎖,由於不容許被更改,只有讀操做,因此就不用考慮多線程致使互斥等問題。
  •  索引一旦被加載到了緩存中,大部分訪問操做都是對內存的讀操做,省去了訪問磁盤帶來的io開銷。
  •  倒排索引具備不可變性,全部基於該索引而產生的緩存也不須要更改,由於沒有數據變動。
  •  倒排索引能夠壓縮數據,減小磁盤io及對內存的消耗。
倒排索引結構:

如圖左邊爲存儲結構,右邊爲倒排索引,將左邊的每條文檔值內容進行分詞而且記錄詞頻和位置,好比咱們如今搜索「集羣」兩字就會直接按照文檔ids進行搜索,獲得文檔一、二、3條記錄,搜索「學習」會獲得文檔一、3兩條記錄。

4、Elasticsearch安裝

1.下載Elasticsearch  Linux版安裝包

官網下載太慢,直接使用我下載好的安裝包

連接:https://pan.baidu.com/s/1Na0K7hIFJbGECD9XCwdR4A 
提取碼:9oz6 
複製這段內容後打開百度網盤手機App,操做更方便哦
2.安裝
  • 解壓
tar -zxvf elasticsearch-7.10.1-linux-x86_64.tar.gz 
  • 將解壓的文件移動到 /usr/local下面
mv elasticsearch-7.10.1  /usr/local
  • 進入目錄查看
cd /usr/local/elasticsearch-7.10.1
ll
  • ES 目錄介紹

bin:可執行文件在裏面,運行es的命令就在這個裏面,包含了一些腳本文件等

config:配置文件目錄

JDK:java環境

lib:依賴的jar,類庫

logs:日誌文件

modules:es相關的模塊

plugins:能夠本身開發的插件

data:這個目錄沒有,本身新建一下,後面要用 -> mkdir data,這個做爲索引目錄

  • 修改核心配置文件 elasticearch.yml
  1. 修改集羣名稱,默認是elasticsearch,雖然目前是單機,可是也會有默認的
  2. 爲當前的es節點取個名稱,名稱隨意,若是在集羣環境中,都要有相應的名字
  3. 修改data數據保存地址
  4. 修改日誌數據保存地址

    5.綁定es網絡ip,原理同redis

    6.默認端口號9200,能夠自定義修改

    7.集羣節點,名字能夠先改爲以前的那個節點名稱

  • 修改JVM參數

默認xms和xmx都是1g,我使用的是虛擬機內存沒這麼大,修改一下便可

vim jvm.options

  • 添加用戶

ES不容許使用root操做es,須要添加用戶,操做以下:

useradd esuser
chown -R esuser:esuser /usr/local/elasticsearch-7.4.2
whoami
  • 解決啓動保存問題
  1. 修改 limits.conf 文件
vim /etc/security/limits.conf

    在尾部添加以下內容

* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096

    2. 修改 sysctl.conf 文件

vim  /etc/sysctl.conf

    在下面添加以下內容

vm.max_map_count=262145

  • 啓動
  1. 切換到剛纔建立的用戶下
su  esuser

    2. 到ES的bin目錄下面

cd /usr/local/elasticsearch-7.10.1/bin

    3.啓動

./elasticsearch  ## 前臺啓動
./elasticsearch -d  ## 後臺啓動
  • 測試

在瀏覽器輸入 虛擬器IP + ES端口號

​9200:Http協議,用於外部通信

9300:Tcp協議,ES集羣之間是經過9300通信

http://192.168.2.223:9200/

成功

  • 安裝ES可視化工具ES-Header

github地址:https://github.com/mobz/elasticsearch-head

爲方便起見我使用Google插件進行安裝,備註:須要能谷歌上網

安裝完成後以下所示爲用ES-Header查看咱們剛纔安裝後的ES節點信息:

 

  • 解決跨域問題

在 elasticearch.yml 中加入以下內容便可:

http.cors.enabled: true
http.cors.allow-origin: "*"

 五、ES文檔的基本操做--增刪改查

一、增長操做

若是索引沒有手動創建mapping,那麼插入文檔數據時,會根據文檔類型自動設置屬性類型。這個就是es動態映射,幫咱們在index索引庫中去創建數據結構的相關配置。
  • 在可視化工具中建一個索引命名爲 my_doc

  • 手動添加文檔數據
在postman裏面發送post請求到http://192.168.2.223:9200/my_doc/_doc/1
注意:my_doc爲索引名、_doc爲文檔類型、1爲爲文檔起的id惟一編號(若是不指定系統會爲每條數據自動分配一個)
添加數據:
http://192.168.2.223:9200/my_doc/_doc/1
{
"id": 1001,
"name": "zhouhong-1",
"desc": "zhouhong is my good fridend!",
"create_date": "2021-02-19"
}

http://192.168.2.223:9200/my_doc/_doc/2
{
"id": 1002,
"name": "zhouhong-2",
"desc": "zhouhong 是一個好人",
"create_date": "2021-02-18"
}

http://192.168.2.223:9200/my_doc/_doc/3
{
"id": 1003,
"name": "zhouhong-3",
"desc": "zhouhong 真的是一個好人",
"create_date": "2021-02-18"
}

http://192.168.2.223:9200/my_doc/_doc/4
{
"id": 1004,
"name": "zhouhong-4",
"desc": "zhouhong is her friend",
"create_date": "2021-02-18"
}

http://192.168.2.223:9200/my_doc/_doc/5
{
"id": 1005,
"name": "zhouhong-5",
"desc": "zhouhong is 好人",
"create_date": "2021-02-18"
}

http://192.168.2.223:9200/my_doc/_doc/6
{
"id": 1006,
"name": "zhouhong-6",
"desc": "zhouhong is realy good man",
"create_date": "2021-02-18"
}
  • 檢查是否添加成功

二、刪除

直接調用 http://192.168.2.223:9200/my_doc/_doc/6 發送DELETE請求既可
注意:這裏的刪除操做不是真正的刪除,只是邏輯上的刪除(添加標識符)ES屬於被動刪除,只有在磁盤滿了的時候會被動刪除。

三、修改請求

直接調用:http://192.168.2.223:9200/my_doc/_doc/6/_update 發送POST請求
入參:
{
    "doc": {
        "name" "周紅"
    }
}

四、查詢

  • 根據文檔id查詢
直接發送GET請求http://192.168.2.223:9200/my_doc/_doc/6
至關於:select * from my_doc where _id = 6
結果:
{
    "_index": "my_doc",
    "_type": "_doc",
    "_id": "6",
    "_version": 2,
    "_seq_no": 17,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "id": 1006,
        "name": "zhouhong-6",
        "desc": "zhouhong is realy good man",
        "create_date": "2021-02-18"
    }
}
_index:文檔數據所屬那個索引,理解爲數據庫的某張表便可。
_type:文檔數據屬於哪一個類型,新版本使用_doc。
_id:文檔數據的惟一標識,相似數據庫中某張表的主鍵。能夠自動生成或者動指定。
_score:查詢相關度,是否契合用戶匹配,分數越高用戶的搜索體驗越高。
_version:版本號。
_source:文檔數據,json格式。
  • 查詢全部
至關於:select * from my_doc
調用 http://192.168.2.223:9200/my_doc/_doc/_search 發送GET請求
  • 查詢部分數據
至關於: select id, name from my_doc where _id = 2
GET請求http://192.168.2.223:9200/my_doc/_doc/1?source=id,name
  • 判斷當前索引是否存在文檔,如下方式比較規範
發送HEAD請求 http://192.168.31.183:9200/my_doc/_doc/2 根據相應狀態碼HttpStatusCode:200,則存在,404則不存在
比使用GET查詢請求判斷文檔是否存在效率更高

 

、ES分詞器

ES默認只支持英文分詞,若是是中文它會拆分爲一個一個字

一、默認分詞器

a.分詞器(會忽略大小寫):
  • 標準分詞器standard(把單詞進行分割)
  • 簡單分詞器simple(會去除字符串中非字母的元素)
  • 空格分詞器whitespace(根據空格進行分割)
  • stop(會去除英文語句中的無心義的單詞:the 、is、a等等)
  • keyword(會將整個文本看成一個詞,不會被拆分)
b.標準分詞器演示:
入參:
{
    "analyzer": "standard",
    "text": "zhouhong is a good man!"
}
結果:
{
    "tokens": [
        {
            "token": "zhouhong",
            "start_offset": 0,
            "end_offset": 8,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "is",
            "start_offset": 9,
            "end_offset": 11,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "a",
            "start_offset": 12,
            "end_offset": 13,
            "type": "<ALPHANUM>",
            "position": 2
        },
        {
            "token": "good",
            "start_offset": 14,
            "end_offset": 18,
            "type": "<ALPHANUM>",
            "position": 3
        },
        {
            "token": "man",
            "start_offset": 19,
            "end_offset": 22,
            "type": "<ALPHANUM>",
            "position": 4
        }
    ]
}

二、IK中文分詞器

1.安裝
下載與ES對應的IK壓縮包上傳服務器
  • 將壓縮包解壓到ES下的 plugins 下
unzip elasticsearch-analysis-ik-7.10.1.zip  -d /usr/local/elasticsearch-7.10.1/plugins/ik
2.測試
  • 使用 ik_max_word(最細粒的拆分) 測試
入參:
{
    "analyzer": "ik_max_word",
    "text": "明天早上吃什麼呢"
}
出參:
{
    "tokens": [
        {
            "token": "明天",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        },
        {
            "token": "早上",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 1
        },
        {
            "token": "吃什麼",
            "start_offset": 4,
            "end_offset": 7,
            "type": "CN_WORD",
            "position": 2
        },
        {
            "token": "什麼",
            "start_offset": 5,
            "end_offset": 7,
            "type": "CN_WORD",
            "position": 3
        },
        {
            "token": "",
            "start_offset": 7,
            "end_offset": 8,
            "type": "CN_CHAR",
            "position": 4
        }
    ]
}
可見分的很詳細,幾乎能組成詞的都拆分了。
  • 使用 ik_smart 分詞器測試
入參:
{
    "analyzer": "ik_smart",
    "text": "明天早上吃什麼呢"
}
出參:

 

{
    "tokens": [
        {
            "token": "明天",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        },
        {
            "token": "早上",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 1
        },
        {
            "token": "吃什麼",
            "start_offset": 4,
            "end_offset": 7,
            "type": "CN_WORD",
            "position": 2
        },
        {
            "token": "",
            "start_offset": 7,
            "end_offset": 8,
            "type": "CN_CHAR",
            "position": 3
        }
    ]
}

三、自定義中文分詞器

IK默認分詞器雖然很好用,可是會存在一個問題,像咱們的網絡用語,姓名等等它會分割爲一個一個的字不符合咱們的需求好比下面這個狀況:
{
    "analyzer": "ik_max_word",
    "text": "周紅"
}

{
    "tokens": [
        {
            "token": "",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
        },
        {
            "token": "",
            "start_offset": 1,
            "end_offset": 2,
            "type": "CN_CHAR",
            "position": 1
        }
    ]
}
咱們但願它是一個完整的詞,而不用被拆分開來。
自定義分詞器
  • 在IK分詞器安裝目錄下面的配置文件,增長一個custom.dic的字典文件
vim /usr/local/elasticsearch-7.10.1/plugins/ik/config/IKAnalyzer.cfg.xml

 

  • 在同級目錄下新建一個custom.dic文件裏面寫上咱們不須要拆分的詞

  • 測試
入參:
{
    "analyzer": "ik_max_word",
    "text": "周紅"
}
出參:
{
    "tokens": [
        {
            "token": "周紅",
            "start_offset": 0,
            "end_offset": 2,
            "type": "CN_WORD",
            "position": 0
        }
    ]
}

 後面若是想擴展,只需在自定義的custom.dic裏面添加詞彙便可

相關文章
相關標籤/搜索