【漫畫】ES原理 必知必會的倒排索引和分詞

来源:https://www.cnblogs.com/liuyanling/archive/2020/05/23/12941917.html
-Advertisement-
Play Games

倒排索引的初衷 倒排索引,它也是索引。索引,初衷都是為了快速檢索到你要的數據。 我相信你一定知道mysql的索引,如果對某一個欄位加了索引,一般來說查詢該欄位速度是可以有顯著的提升。 每種資料庫都有自己要解決的問題(或者說擅長的領域),對應的就有自己的數據結構,而不同的使用場景和數據結構,需要用不同 ...


es1

倒排索引的初衷

es2_1

倒排索引,它也是索引。索引,初衷都是為了快速檢索到你要的數據。

我相信你一定知道mysql的索引,如果對某一個欄位加了索引,一般來說查詢該欄位速度是可以有顯著的提升。
每種資料庫都有自己要解決的問題(或者說擅長的領域),對應的就有自己的數據結構,而不同的使用場景和數據結構,需要用不同的索引,才能起到最大化加快查詢的目的。
對 Mysql 來說,是 B+ 樹,對 Elasticsearch/Lucene 來說,是倒排索引。

es2_2

倒排索引是什麼

剛剛胖滾豬說到圖書的例子,目錄和索引頁,其實就很形象的可以比喻為正排索引和倒排索引。為了進一步加深理解,再看看熟悉的搜索引擎。沒有搜索引擎時,我們只能直接輸入一個網址,然後獲取網站內容,這時我們的行為是document -> words。此謂「正向索引」。後來,我們希望能夠輸入一個單詞,找到含有這個單詞,或者和這個單詞有關係的文章,即word -> documents。於是我們把這種索引,叫「反向索引」,或者「倒排索引」。
好了,我們來總結一下:

image

es3

倒排索引的實現

假如一篇文章當中,有這麼一段話"胖滾豬編程讓你收穫快樂",我要通過"胖滾豬"這個詞來搜索到這篇文章,那麼應該如何實現呢。

我們是很容易想到,可以將這篇文章的詞都拆開,拆分為"胖滾豬"、"編程"、"收穫"、"快樂"。註意我們把沒用的詞,比如"讓"去掉了。這個拆分短語的過程涉及到ES的分詞,另外中文分詞還是比較複雜的,不像英文分詞一般用空格分隔就可以。等會我們再來說分詞吧,現在你只要知道,我們是會按一定規則把文章單詞拆分的。
那麼拆開了,怎麼去找呢?自然會維護一個單詞和文檔的對應關係,如圖:

image
es4

倒排索引的核心組成

1、單詞詞典:記錄所有文檔的單詞,一般都比較大。還會記錄單詞到倒排列表的關聯信息。
2、倒排列表:記錄了單詞對應的文檔集合,由倒排索引項組成。倒排索引項包含如下信息:

  • 文檔ID,用於獲取原始信息
  • 單詞頻率TF,記錄該單詞在該文檔中的出現次數,用於後續相關性算分
  • 位置Position,記錄單詞在文檔中分詞的位置,用於語句搜索(phrase query)
  • 偏移Offset,記錄單詞在文檔的開始和結束位置,實現高亮顯示

es6

ES的倒排索引

下圖是 Elasticsearch 中數據索引過程的流程。ES由 Analyzer 組件對文檔執行一些操作並將具體子句拆分為 token/term,簡單說就是分詞,然後將這些術語作為倒排索引存儲在磁碟中。
image

ES的JSON文檔中的每一個欄位,都有自己的倒排索引,當然你可以指定某些欄位不做索引,優點是這樣可以節省磁碟空間。但是不做索引的話欄位無法被搜索到。
註意兩個關鍵詞:分詞和倒排索引。倒排索引我相信你已經懂了!分詞我們馬上就來聊聊!

ES的分詞

還是回到我們開頭的那個查詢例子,畢竟胖滾豬心心念念為什麼會搜出兩個文檔!首先我們用_analyze來分析一下ES會如何對它進行分詞及倒排索引:
image

現在你是不是一目瞭然了呢!先不管_analyze是何方神聖,反正你看到結果了,ES將它分成了一個個字,這是ES中預設的中文分詞。掌握分詞要先懂兩個名詞:analysis與analyzer

** analysis:**

文本分析,是將全文本轉換為一系列單詞的過程,也叫分詞。analysis是通過analyzer(分詞器)來實現的,可以使用Elasticearch內置的分詞器,也可以自己去定製一些分詞器。

** analyzer(分詞器): **

由三部分組成:

  • Character Filter:將文本中html標簽剔除掉。
  • Tokenizer:按照規則進行分詞,在英文中按照空格分詞
  • Token Filter:將切分的單詞進行加工,小寫,刪除 stopwords(停頓詞,a、an、the、is等),增加同義詞

註意:除了在數據寫入時將詞條進行轉換,查詢的時候也需要使用相同的分析器對語句進行分析。即我們寫入蘋果的時候分詞成了蘋和果,查詢蘋果的時候同樣也是分詞成蘋和果去查。
es7

ES內置分詞器

  • Standard Analyzer - 預設分詞器,按詞切分,小寫處理
  • Simple Analyzer - 按照非字母切分(符號被過濾), 小寫處理
  • Stop Analyzer - 小寫處理,停用詞過濾(the,a,is)
  • Whitespace Analyzer - 按照空格切分,不轉小寫
  • Keyword Analyzer - 不分詞,直接將輸入當作輸出
  • Patter Analyzer - 正則表達式,預設\W+(非字元分割)
  • Language - 提供了30多種常見語言的分詞器
  • Customer Analyzer 自定義分詞器

看概念太虛了!一定要動手實操才有用!我們可以用_analyze進行分析,會輸出分詞後的結果,舉兩個例子吧!其他的你也要自己課後動手試試哦!

#預設分詞器 按詞切分 小寫處理
GET _analyze
{
  "analyzer": "standard",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}
​
#可以發現停用詞被去掉了
GET _analyze
{
  "analyzer": "stop",
  "text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

中文擴展分詞器

現在來解決胖滾豬的問題,蘋果明明一個詞,不想讓它分為兩個呀!中文分詞在所有搜索引擎中都是一個很大的難點,中文的句子應該是切分成一個個的詞,但是一句中文,在不同的上下文,其實是不同的理解,例如: 這個蘋果,不大好吃/這個蘋果,不大,好吃。

有一些比較不錯的中文分詞插件:IK、THULAC等。我們可以試試用IK進行中文分詞。

#安裝插件
https://github.com/medcl/elasticsearch-analysis-ik/releases
在plugins目錄下創建analysis-ik目錄 解壓zip包到當前目錄 重啟ES
#查看插件
bin/elasticsearch-plugin list
#查看安裝的插件
GET http://localhost:9200/_cat/plugins?v

** IK分詞器:支持自定義詞庫、支持熱更新分詞字典 **

  • ik_max_word: 會將文本做最細粒度的拆分,比如會將“這個蘋果不大好吃”拆分為"這個,蘋果,不大好,不大,好吃"等,會窮盡各種可能的組合;
  • ik_smart: 會做最粗粒度的拆分,比如會將“這個蘋果不大好吃”拆分為"這個,蘋果,不大,好吃"
curl -X GET "localhost:9200/_analyze?pretty" -H 'Content-Type: application/json' -d'
{
  "analyzer" : "ik_max_word",
  "text" : "這個蘋果不大好吃"
}
'

es8

** 如何使用分詞器 **

列舉了很多的分詞器,那麼在實際中該如何使用呢?看看下麵這個代碼演示就懂啦!

# 創建索引時候指定某個欄位的分詞器
PUT iktest
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "analyzer": "ik_smart"
      }
    }
  }
}
# 插入一條文檔
PUT iktest/_doc/1
{
  "content":"這個蘋果不大好吃"
}
# 測試分詞效果
GET /iktest/_analyze
{
  "field": "content",
  "text": "這個蘋果不大好吃"  
}
​

註:本文來源於公眾號[胖滾豬學編程],其中卡通形象來源於微信表情包"胖滾家族",且已獲作者的許可。

wchat1

本文來源於公眾號【胖滾豬學編程】一個集顏值與才華於一身的女程式媛。以漫畫形式讓編程so easy and interesting。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前期準備 執行yum update openssh先升級下. 反正官方提供的這種升級是沒問題的。如果之前手動編譯操作過openssh的升級,變更了預設配置文件路徑什麼的請自行測試。) (這裡準備統一openssh版本為7.4p1之後再統一編譯安裝升級到openssh8.2p1) [root@node ...
  • pwd命令 功能說明:顯示當前用戶所在的工作目錄 用法:pwd [OPTION]... 當我們登錄操作系統時,我們就會處在某個目錄中,windows為桌面,在Linux操作系統中,如果我們以root用戶登錄,我們會處在root用戶的家目錄,如果以普通用戶登錄,我們會處在普通用戶的家目錄。 | 選項 ...
  • HBase為每個Region維護一個狀態,並將該狀態保留在hbase:meta中。hbase:meta 本身的Region狀態保留在ZooKeeper中。可以在Master Web UI中查看Region的過渡狀態。以下是可能的Region狀態列表。 1. 狀態機中包括下麵幾種狀態: offline ...
  • 本文來源於公眾號:胖滾豬學編程。轉載請註明出處! 一個風度翩翩,穿著格子襯衣的中年男子,拿著一個滿是劃痕的mac向她走來,看著錚亮的頭,胖滾豬心想,這肯定是尼瑪頂級架構師吧!完了要掛了。 結果面試官第一個問題,就讓胖滾豬內心暗喜 面試官 :消息隊列這東西,你還熟悉吧?消息隊列在企業中的應用場景有哪些 ...
  • 上一篇 我們模擬了單機器下哨兵模式的搭建,那麼接下來我們看下哨兵模式的實現與工作。 為什麼又分成兩篇呢?因為篇幅太長(偷懶),再一個這篇主要說的是Sentinel的初始化以及信息交換,下一篇著重說下狀態檢查、Sentinel頭領選舉與故障轉移 。 啟動並初始化Sentinel 當一個Sentinel ...
  • 前言: 本文主要講述瞭如何使用Docker快速上手HBase,省去繁雜的安裝部署環境,直接上手,小白必備。適合HBase入門學習及簡單代碼測試。 1. Docker 安裝 參考地址: 支持常用的操作系統:Centos / ubuntu / Windows / macos 等。 2. 拉取鏡像 鏡像地 ...
  • 下麵的testa表沒有數據,dept表有數據。直接select,有數據就會有結果集。 plsql的exists用於判斷子查詢是否有結果集返回,“exists (子查詢)”子查詢只要結果集有數據,則exists判斷為true,否則為false,不管結果集數據是什麼,是1啊是2啊或者很多列,只要結果集不 ...
  • DDL:用來定義RDB模式、外模式和內模式,已實現對基本表、視圖以及索引文件的定義、修改和刪除 創建數據表->創建表結構->創建表數據 數據類型 創建表 create table 表名( 欄位名 數據類型 [長度] [列級完整性約束][表級完整性約束]--多個主鍵:primary key (欄位名, ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...