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


lucene、Solr、Elasticsearch

1、倒排序索引

2、Lucene是類庫

3、solr基於lucene

4、ES基於lucene

一、Elasticsearch 核心術語

特點:
1、es可以支持空格查詢,多個關鍵字

2、空格支持

3、拆詞查詢

4、搜索內容可以高亮

5、海量數據查庫
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(備份節點)

二、ES集群架構原理

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

shard和replica機制   

A、index包含多個shard   

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

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

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放在同一節點上

三、倒排索引

ES為什么這么快?

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

        2、倒排索引是不可更改的,一旦它被建立了,里面的數據就不會再進行更改。這樣做就帶來了以下幾個好處:

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

如圖左邊為存儲結構,右邊為倒排索引,將左邊的每條文檔值內容進行分詞並且記錄詞頻和位置,比如我們現在搜索“集群”兩字就會直接按照文檔ids進行搜索,得到文檔1、2、3條記錄,搜索“學習”會得到文檔1、3兩條記錄。

四、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文檔的基本操作--增刪改查

1、增加操作

如果索引沒有手動建立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"
}
  • 檢查是否添加成功

2、刪除

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

3、修改請求

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

4、查詢

  • 根據文檔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默認只支持英文分詞,如果是中文它會拆分為一個一個字

1、默認分詞器

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
        }
    ]
}

2、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
        }
    ]
}

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里面添加詞匯即可

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM