Elasticsearch系列---倒排索引原理與分詞器

概要

本篇主要講解倒排索引的基本原理以及ES經常使用的幾種分詞器介紹。java

倒排索引的創建過程

倒排索引是搜索引擎中常見的索引方法,用來存儲在全文搜索下某個單詞在一個文檔中存儲位置的映射。經過倒排索引,咱們輸入一個關鍵詞,能夠很是快地獲取包含這個關鍵詞的文檔列表。node

咱們先看英文的,假設咱們有兩個文檔:git

  1. I have a friend who loves smile
  2. love me, I love you

爲了創建倒排索引,咱們先按最簡單的用空格把每一個單詞分開,能夠獲得以下結果:
*表示該列文檔中有這個詞條,爲空表示沒有該詞條github

Term doc1 doc2
I * *
have *
a *
friend *
who *
loves *
smile *
love *
me *
you *

若是咱們要搜索 I love you,咱們只須要查找包含每一個詞條的文檔:架構

Term doc1 doc2
I * *
love *
you *

兩個文檔都能匹配上,若是按命中詞條數量來算,doc2比doc1更匹配。併發

這個是倒排索引最簡化的表達方式,在ES的倒排索引存儲結果中,還會記錄每一個詞條在文檔中出現的位置。elasticsearch

指望的分詞處理

咱們再看一下這個索引的創建過程,loves和love有區別嗎?沒有,都是愛的意思,一個是第三人稱單數,一個是原形。若是能將一些語法的區別處理掉,這樣的搜索結果是否是更切合實際需求?
例如:分佈式

  • loves提取詞幹處理成love
  • a,have之類的無實義的詞,直接屏蔽掉
  • 等等

如今索引看上去成這樣:高併發

Term doc1 doc2
friend *
love * *
smile *
me *
you *

這樣是否是精簡了不少?
這個過程叫normalization,在創建倒排索引的時候,會執行一系列的操做,對拆分出的各個單詞進行相應的處理,以提高後面搜索的時候可以搜索到相關聯的文檔的機率,如時態的轉換,單複數的轉換,同義詞的轉換,大小寫的轉換等。學習

分詞器登場

分詞器的做用就是把整篇文檔,按必定的語義切分紅一個一個的詞條,目標是提高文檔的召回率,並下降無效數據的噪音。

recall召回率,也叫可搜索性,指搜索的時候,增長可以搜索到的結果的數量。
降噪:指下降文檔中一些低相關性詞條對總體搜索排序結果的干擾。

文檔的分詞過程包含如下幾步:

  • 字符過濾器

對字符串進行預處理,如HTML標籤清洗<span>Love</span> --> Love,I & you --> I and you等等。

  • 分詞器

把字符串切分紅單個的詞條,如英文的按空格和標點切分,中文的按詞語切分,針對不一樣的語言,有不一樣的分詞器,有相對簡單的標準分詞器,也有特別複雜的中文分詞器,裏面包含了很是複雜的切分邏輯如:

I Love you --> I/Love/you

我和個人祖國 --> 我/和/個人/祖國

  • Token過濾器

將分詞器獲得的詞條進一步的處理,如改變詞條(英文詞幹提取loves --> love),刪除無實際意義的詞條(英文的a, and, this,中文的"的","了","嗎"),增長詞條(補充同義詞)

分詞器很是重要,好的分詞器能夠顯著提高召回率,不恰當的分詞器獲得的結果可能會對搜索產生歧義,最後處理好的結果再拿去創建倒排索引。

常見分詞器介紹

Elasticsearch自身提供了內置的分詞器,也容許使用第三方的分詞器。

內置分詞器

  • 標準分詞器standard analyzer

ES默認分詞器,根據Unicode聯盟定義的單詞邊界劃分文本,刪除絕大部分標點,最後將詞條小寫。

  • 簡單分詞器simple analyzer

在任何不是字母的地方分隔文本,將詞條小寫

  • 空格分詞器whitespace analyzer

在空格的地方劃分文本

  • 語言分詞器language analyzer

特定的語言的分詞器,如english,英語分詞器,維護了一組英語停用詞and、the之類的,用於刪除詞條,針對英文語法規則,有提取單詞詞幹的能力。

內置的分詞器主要是對英文的支持效果比較好,中文則須要使用外部的分詞器。

外部分詞器

  • IK中文分詞器ik_max_word

會將文本作最細粒度的拆分;儘量多的拆分出詞語。
如南京市長江大橋 --> 南京市/南京/市長/長江大橋/長江/大橋

  • IK中文分詞器ik_smart

會作最粗粒度的拆分;已被分出的詞語將不會再次被其它詞語佔有
如南京市長江大橋 --> 南京市/長江大橋

  • 中日韓文分詞器cjk

支持亞洲語言中文,日文,韓文
如南京市長江大橋 --> 南京/京市/市長/長江/江大/大橋

  • 阿里中文分詞器aliws

阿里自研的中文分詞器
如南京市長江大橋 --> 南京/市/長江/大橋

外部分詞器衆多,開源也有不少,有針對不一樣語言,不一樣領域的,各位能夠結合自身業務的特色,挑選適合本身的分詞器,這裏就不一一介紹了,有興趣本身能夠去了解一下。

集成分詞器

以Elasticsearch 6.3.1版本爲例,集成IK分詞器,其餘的分詞器過程也相似,在ES的bin目錄下執行插件安裝命令便可:
./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.1/elasticsearch-analysis-ik-6.3.1.zip

其中install後面的那個的地址是 elasticsearch-analysis-ik 的github release對應ES版本的下載地址。

安裝成功後,ES啓動日誌就能看到以下信息:
[2019-11-27T12:17:15,255][INFO ][o.e.p.PluginsService] [node-1] loaded plugin [analysis-ik]

測試分詞效果

ES有analyze API來查看文本是如何被分詞的,可用來作學習和調試用,請求命令以下:

GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "南京市長江大橋"
}

響應結果:

{
  "tokens": [
    {
      "token": "南京市",
      "start_offset": 0,
      "end_offset": 3,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "南京",
      "start_offset": 0,
      "end_offset": 2,
      "type": "CN_WORD",
      "position": 1
    },
    {
      "token": "市長",
      "start_offset": 2,
      "end_offset": 4,
      "type": "CN_WORD",
      "position": 2
    },
    {
      "token": "長江大橋",
      "start_offset": 3,
      "end_offset": 7,
      "type": "CN_WORD",
      "position": 3
    },
    {
      "token": "長江",
      "start_offset": 3,
      "end_offset": 5,
      "type": "CN_WORD",
      "position": 4
    },
    {
      "token": "大橋",
      "start_offset": 5,
      "end_offset": 7,
      "type": "CN_WORD",
      "position": 5
    }
  ]
}

小結

本篇主要介紹了倒排索引的基本思路,展現了簡化後的結構,並闡述了分詞處理的基本步驟。目前市面上流行的分詞器組件特別多,開源的社區也很是活躍,各位可根據實際的項目需求背景,挑選適合的進行集成 ,注意版本號的兼容性問題便可。

專一Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公衆號:Java架構社區
Java架構社區.jpg

相關文章
相關標籤/搜索