反向索引
反向索引以字或詞為關鍵字進行索引,表中關鍵字所對應的記錄表項記錄了出現這個字或詞的所有文檔,一個表項就是一個字表段。它記錄該文檔的ID和字元在該文檔中出現的位置情況。
以下三個文檔去除停用詞後構造反向索引
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP35ENRRVTyEkaNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4QDNyIjN1UTM3IDOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
- Term(單詞): 一段文本經過分析器以後就會輸出一串單詞,這一個個的就叫做Term
- Term Dictionary(單詞字典) 顧名思義,它裡面維護的是Term,可以了解為Term的集合
- Term Index(單詞索引): 為了更快的找到某個單詞,我們為單詞建立索引
-
Posting List(倒排清單): 倒排清單記錄了出現過的某個單詞的所有文檔的文檔清單及單詞在該文檔中出現的位置資訊,每條記錄稱為一個倒排項。
根據倒排清單,即可知哪些文檔包含某個單詞。
(PS: 如果類比現代漢語詞典的話,那麼Term就相當于詞語,Term Dictionary相當于漢語詞典本身,Term Index相當于詞典的目錄索引)
上面的例子,Elasticsearch建立的索引大緻如下:
name字段
age字段
gender字段
address字段
Elasticsearch分别為每個字段都建立一個反向索引。比如,在上面”張三“,”北京市“,22 這些都是Term,而[1,3]就是Posting List。Posting list就是一個數組,存儲了所有符合某個Term的文檔ID。
反向索引的組成
- 單詞清單:實作一般用B+樹,
- 倒排清單
- 文檔id用于擷取原始資訊
- 單詞頻率(TF,Term Frequency),記錄該單詞在該文檔中出現的次數。
- 位置(Posting),記錄單詞在文檔中的分詞位置,用于做詞語搜尋
- 偏移(Offset),記錄單詞在文檔的開始和結束位置,用于高亮顯示
建立了B-Tree來快速找到Terms索引
MyISAM中,索引和資料是分開,通過索引可以找到記錄的位址,進而可以找到這條記錄
前面分成了三步,其實可以把Term Index和Term Dictionary看成一步,就是找Term。是以可以這樣了解反向索引:通過單詞找到對應的倒排清單,根據倒排清單中的倒排進而可以找到文檔記錄
反向索引不可變的好處
- 不需要鎖,提升并發能力,避免鎖問題
- 資料不變,一直儲存在os cache中,隻要cache記憶體足夠
- filter cache一直駐留在記憶體,因為資料不變
- 可以壓縮,節省cpu和io開銷
分詞
分詞是将文本轉換為一系列單詞的過程,也可以叫文本分析,在ES裡面稱為Analysis
比如下面這一句
- Elasticsearch是最流行的搜尋引擎
- Elasticsearch / 流行 / 搜尋引擎
分詞器有以下組成:
- Character Filter: 針對原始文本進行處理,比如去除html标簽
- Tokenizer: 将原始文本按照一定規則切分為單詞
- Token Filter: 針對Tokenizer處理的單詞進行再加工,比如轉小寫,删除或增新等處理
Analyzer分詞器的調用順序
- Character Filter
- Tokenizer
- Token Filter
預定義的分詞器
-
Standard Analyzer
預設分詞器
按詞切分,支援多語言
小寫處理
-
Simple Analyzer
按照非字母切分
小寫處理
-
Whitespace Analyzer
空白字元作為分隔符
-
Stop Analyzer
相比Simple Analyzer多了去除請用詞處理
停用詞指語氣助詞等修飾性詞語,如the an,的,這等
-
keyword Analyzer
不分詞,直接将輸入作為一個單詞輸出
-
pattern Analyzer
通過正規表達式自定義分詞符
預設是\W+ ,即非字詞的符号作為分隔符
-
Language Analyzer
提供了30+種常見的語言的分詞器
自定義分詞器
Character Filters
- 在Tokenizer之前對原始文本進行處理,比如增加,删除或替換字元等。
- 自帶的如下:
- HTML Strip Character Filter:去除HTML标簽和轉換HTML實體
- Mapping Character Filter:進行字元串替換操作
- Pattern Replace Character Filter:進行正則比對替換
- 會影響後續tokenizer 解析的position和offset資訊
Tokenizers
- 将原始文本按照一定規則切分為單詞(term or token)
- 自帶如下:
- standard按照單詞進行分割
- letter按照非字元進行分割
- whitespace按照空格進行分割
- UXA URL Email按照standard進行分割,但不會分割郵箱和URL
- Ngram 和Edge NGram連詞分割
- Path Hierarchy 按照檔案路徑進行分割
Token Filters
- 對于tokenizer輸出的單詞(term) 進行增加,删除,修改等操作
- 自帶的如下:
- lowercase 将所有的term轉為小寫
- stop删除停用詞
- Ngram和Edge NGram連詞分割
- Synonym添加近義詞的term
自定義分詞。。。。
分詞使用說明
分詞會在如下兩個時機使用:
- 建立或更新文檔時,會對響應的文檔進行分詞處理
- 查詢(Search Time),會對查詢語句進行分詞
- 查詢時通過analyzer指定分詞器
- 通過index mapping設定search_analyzer實作
- 一般不需要特别指定查詢時分詞器,直接使用索引分詞器即可,否則會出現無法比對的情況
分詞使用建議
- 明确字段是否需要分詞,不需要分詞的字段就将type設定為keyword,可以節省空間提高性能
- 善用_analyze API ,檢視文檔的分詞結果