ES 09 - Elasticsearch如何定制分詞器 (自定義分詞策略)


1 索引的分析

索引分析: 就是把輸入的文本塊按照一定的策略進行分解, 並建立倒排索引的過程. 在Lucene的架構中, 這個過程由分析器(analyzer)完成.

1.1 分析器的組成

① 字符過濾器(character filter): 比如去除HTML標簽、把&替換為and等.

② 分詞器(tokenizer): 按照某種規律, 如根據空格、逗號等, 將文本塊進行分解.

③ 標記過濾器(token filter): 所有被分詞器分解的詞都將經過token filters的處理, 它可以修改詞(如小寫化處理)、去掉詞(根據某一規則去掉無意義的詞, 如"a", "the", "的"等), 增加詞(如同義詞"jump"、"leap"等).

注意: 人們一般將分析器通稱為分詞器, 並不是相等的關系, 而是包含的關系.

1.2 倒排索引的核心原理-normalization

建立倒排索引時, 會執行normalization(正常化)操作 —— 將拆分的各個單詞進行處理, 以提高搜索時命中關聯的文檔的概率.

normalization的方式有: 時態轉換, 單復數轉換, 同義詞轉換, 大小寫轉換等.

比如文檔中包含His mom likes small dogs:
① 在建立索引的時候normalization會對文檔進行時態、單復數、同義詞等方面的處理;
② 然后用戶通過近似的mother liked little dog, 也能搜索到相關的文檔.

2 ES的默認分詞器

(1) ES中的默認分詞器: standard tokenizer, 是標准分詞器, 它以單詞為邊界進行分詞. 具有如下功能:

① standard token filter: 去掉無意義的標簽, 如<>, &, - 等.
② lowercase token filter: 將所有字母轉換為小寫字母.
③ stop token filer(默認被禁用): 移除停用詞, 比如"a"、"the"等.

(2) 測試默認分詞器:

GET _analyze			// ES引擎中已有standard分詞器, 所以可以不指定index
{
    "analyzer": "standard", 
    "text": "There-is & a DOG<br/> in house"
}

可以發現, Elasticsearch對text文本進行了分析處理, 結果如下:

{
  "tokens" : [
    {
      "token" : "there",      // 分詞
      "start_offset" : 0,     // 起始偏移量
      "end_offset" : 5,       // 結束偏移量
      "type" : "<ALPHANUM>",  // 分詞的類型
      "position" : 0          // 該分詞在文本中的位置
    },
    {
      "token" : "is",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "a",
      "start_offset" : 11,
      "end_offset" : 12,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    // 省略其他4項
  ]
}

3 修改分詞器

(1) 創建索引后可以添加新的分詞器:

說明: 必須先關閉索引, 添加完成后, 再及時打開索引進行搜索等操作, 否則將出現錯誤.

// 關閉索引:
POST address/_close

// 啟用English停用詞token filter
PUT address/_settings
{
    "analysis": {
        "analyzer": {
            "my_token_filter": {        // 自定義的分詞器名稱
                "type": "standard",
                "stopwords": "_english_"
            }
        }
    }
}

// 打開索引:
POST address/_open

(2) 使用具有停詞功能的分詞器進行分詞:

GET address/_analyze      // 指定索引
{
    "analyzer": "my_token_filter",   // 指定要使用的分詞器
    "text": "There-is & a DOG<br/> in house"
}

(3) 返回結果減少了停用詞there, is, &, a, in等:

{
  "tokens" : [
    {
      "token" : "dog",
      "start_offset" : 13,
      "end_offset" : 16,
      "type" : "<ALPHANUM>",
      "position" : 3
    },
    {
      "token" : "br",
      "start_offset" : 17,
      "end_offset" : 19,
      "type" : "<ALPHANUM>",
      "position" : 4
    },
    {
      "token" : "house",
      "start_offset" : 25,
      "end_offset" : 30,
      "type" : "<ALPHANUM>",
      "position" : 6
    }
  ]
}

4 定制分詞器

4.1 向索引中添加自定義的分詞器

同樣的, 在添加新的分詞器之前, 必須先關閉索引, 添加完成后, 再打開索引進行搜索等操作.

PUT address/_settings
{
    "analysis": {
        "char_filter": {
            "&_to_and": {
                "type": "mapping",
                "mappings": ["& => and"]
            }
        },
        "filter": {
            "my_stopwords": {
                "type": "stop",
                "stopwords": ["the", "a"]
            }
        },
        "analyzer": {
            "my_analyzer": {    // 自定義的分析器名稱
                "type": "custom",
                "char_filter": ["html_strip", "&_to_and"], // 跳過HTML標簽, 將&符號轉換為"and"
                "tokenizer": "standard",
                "filter": ["lowercase", "my_stopwords"]    // 轉換為小寫
            }
        }
    }
}

4.2 測試自定義分析器

GET address/_analyze
{
    "analyzer": "my_analyzer",   // 上面定義的分析器名稱
    "text": "There-is & a DOG<br/> in house"
}

可以發現, 返回的分析結果中已經對大寫單詞、HTML標簽, 以及"&"做了處理.

{
  "tokens" : [
    // there和is
    {
      "token" : "and",      // &被處理成了and
      "start_offset" : 9,
      "end_offset" : 10,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    // dog、in和house
  ]
}

4.3 向映射中添加自定義的分詞器

PUT address/_mapping/province
{
    "properties": {
        "content": {
            "type": "text",
            "analyzer": "my_analyzer"
        }
    }
}

此時查看mapping信息:

GET address/_mapping

發現自定義的分析器已經配置到province上了:

{
  "address": {
    "mappings": {
      "province": {
        "properties": {
          "area" : {
            "type" : "float"
          },
          "content" : {
            "type" : "text",
            "analyzer" : "my_analyzer"
          },
          "name" : {
            "type" : "text"
          }
        }
      }
    }
  }
}

5 常見問題

在修改索引之前, 沒有關閉索引, 修改時發生如下錯誤:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "Can't update non dynamic settings [[index.analysis.analyzer.my_token_filter.type, index.analysis.analyzer.my_token_filter.stopwords]] for open indices [[address/Ci6MJV4sTyuoF4r9aLvVZg]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "Can't update non dynamic settings [[index.analysis.analyzer.my_token_filter.type, index.analysis.analyzer.my_token_filter.stopwords]] for open indices [[address/Ci6MJV4sTyuoF4r9aLvVZg]]"
  },
  "status": 400
}

查看本篇第[3]節的說明, 先關閉索引再執行修改操作.

版權聲明

作者: 馬瘦風(https://healchow.com)

出處: 博客園 馬瘦風的博客(https://www.cnblogs.com/shoufeng)

感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜

本文版權歸博主所有, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文鏈接], 否則博主保留追究相關人員法律責任的權利.


免責聲明!

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



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