Elasticsearch分词

 分词,Analysis,就是将文本转换成一系列单词的过程。

 

 Analyzer分词器

  Analyzer主要是对输入的文本类内容进行分析(通常是分词),将分析结果以term的形式进行存储。

 

  针对text类型,选择合适的分词器很重要

  Analyzer由三部分组成:Character Filters、Tokenizer、Token Filters

  1):Character Filters

    Character Filters 以 characters 流的方式接收原始数据,它可以支持 characters 的增、删、改,通常内置的分析器都没有设置默认的 Character Filters,ES 内置的 Character Filters:

    ①、HTML Strip Character Filter:支持剔除 html 标签,解码

    ②、Mapping Character Filter:支持根据定义的映射进行替换

    ③、Pattern Replace Character Filter:支持根据正则进行替换

  2):Tokenizer

    Tokenizer 接收一个字符流,分解成独立的 tokens(通常就是指的分词),并且输出 tokens。

    例如,一个 whitespace tokenizer(空格 tokenizer),以空格作为分割词对输入内容进行分词。例如:向 whitespace tokenizer 输入“Quick brown fox!”,将会输出“Quick”、 “brown”、“fox!” 3 个 token

  3):Token Filters

    Token filters 接收 Tokenizer 输出的 token 序列,它可以根据配置进行 token 的增、删、改。例如:指定 synonyms 增加 token、指定 remove stopwords 进行 token 删除,抑或是使用 lowercasing 进行小写转换

 

 Elasticsearch内置分词器

  ES 内置的分析器有Standard Analyzer、Simple Analyzer、Whitespace Analyzer、Stop Analyzer、Keyword Analyzer、Pattern Analyzer、Language Analyzers、Fingerprint Analyzer,并且支持定制化

  ①:Standard Analyzer:默认的分词器,按词划分,小写处理

    text类型默认的分词器,不适合于中文

    Standard Analyzer 的组成部分:

      TokenizerStandard Tokenizer:

        基于 Unicode 文本分割算法-Unicode 标准附件# 29,支持使用 max_token_length 参数指定 token 长度,默认为 255。

      Token Filters:

        Lower Case Token Filter

        Stop Token Filter :默认没有 stop token/words,需通过参数 stopwords 或 stopwords_path 进行指定 

    如果 text 类型没有指定 Analyzer,Standard Analyzer,前面我们已经了解了 ES 分析器的结构,理解它的分析器应该不在话下。Unicode 文本分割算法依据的标准,给出了文本中词组、单词、句子的默认分割边界。该附件在 notes 中提到,像类似中文这种复杂的语言,并没有明确的分割边界,简而言之就是说,中文并不适用于这个标准
    通常我们的全文检索使用场景都是针对中文的,所以我们在创建我们的映射关系时,一定要指定合适的分析器       
    

GET _analyze
{
  "analyzer": "standard",
  "text": "电视商城"
}

{
  "tokens" : [
    {
      "token" : "电",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "视",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "商",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "城",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    }
  ]
}

  ②:Simple Analyzer——按照非字母切分(符号被过滤),小写处理

GET _analyze
{
  "analyzer": "simple",
  "text": "电视商城"
}

{
  "tokens" : [
    {
      "token" : "电视商城",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "word",
      "position" : 0
    }
  ]
}

  ③:Stop Analyzer——小写处理,停用词过滤(the,is,a)

  ④:Whitespace Analyzer——按照空格切分,不转小写

  ⑤:Keyword Analyzer——不分词,直接将输入当做输出

    keyword类型默认分词器

  ⑥:Pattern Analyzer——正则表达式,默认 \W+(非字符分隔)

 

 

 一、中文分词

  分词插件:IK Analysis Plugin

  简介:

    IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。 最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目, 同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化

  

  特性:

    ①:采用了特有的“正向迭代最细粒度切分算法“,支持细粒度和智能分词两种切分模式

    ②:在系统环境:Core2 i7 3.4G双核,4G内存,window 7 64位, Sun JDK 1.6_29 64位 普通pc环境测试,IK2012具有160万字/秒(3000KB/S)的高速处理能力

    ③:2012版本的智能分词模式支持简单的分词排歧义处理和数量词合并输出

    ④:采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符

    ⑤:优化的词典存储,更小的内存占用。支持用户词典扩展定义。特别的,在2012版本,词典支持中文,英文,数字混合词语

 

  分词方式:

Analyzer Introduction
ik_smart

会做最粗粒度的拆分,适合 Phrase 查询

ik_max_word 会将文本做最细粒度的拆分,会穷尽各种可能的组合,适合 Term Query

 

  分词配置:

    配置文件:IKAnalyzer.cfg.xml can be located at {conf}/analysis-ik/config/IKAnalyzer.cfg.xml or {plugins}/elasticsearch-analysis-ik-*/config/IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 扩展配置</comment>
    <!--用户可以在这里配置自己的扩展字典 -->
    <entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
     <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords">custom/ext_stopword.dic</entry>
     <!--用户可以在这里配置远程扩展字典 -->
    <entry key="remote_ext_dict">location</entry>
     <!--用户可以在这里配置远程扩展停止词字典-->
    <entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>
</properties>

    修改字典中的词条后,等待约1min,就会完成词库的热更新。

 

  分词效果:

    1、ik_smart

GET _analyze
{
  "text": ["结婚的和尚未结婚的"],
  "analyzer": "ik_smart"
}

     result:

{
  "tokens" : [
    {
      "token" : "结婚",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "的",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "和尚",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "未",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "CN_CHAR",
      "position" : 3
    },
    {
      "token" : "结婚",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "的",
      "start_offset" : 8,
      "end_offset" : 9,
      "type" : "CN_CHAR",
      "position" : 5
    }
  ]
}
View Code

 

 

    2、ik_max_word

GET _analyze
{
  "text": ["结婚的和尚未结婚的"],
  "analyzer": "ik_max_word"
}

    result:

{
  "tokens" : [
    {
      "token" : "结婚",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "的",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "和尚",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "尚未",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "未结",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "结婚",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "的",
      "start_offset" : 8,
      "end_offset" : 9,
      "type" : "CN_CHAR",
      "position" : 6
    }
  ]
}
View Code

 

  

  更多IK Analysis Plugin介绍请访问: https://github.com/medcl/elasticsearch-analysis-ik

   下载:https://code.google.com/archive/p/ik-analyzer/

 

 

 

 二、拼音分词

  拼音分词器:https://github.com/medcl/elasticsearch-analysis-pinyin

  1、安装:

    ①:通过releases找到和es对应版本的zip文件,或者source文件(自己通过mvn package打包);当然也可以下载最新master的代码

    

    ②:进入elasticsearch安装目录/plugins,创建拼音文件夹:mkdir pinyin,切换到pinyin 目录:cd pinyin

    ③:将zip文件复制到pinyin目录,并解压

      pinyin文件夹下内容如下:

      

    ④:重启ES

  2、配置

    ①:索引配置

    关闭索引:POST my_index/_close

    索引配置:

 

PUT /my_index/ 
{
   "settings" : {
       "analysis" : {
           "analyzer" : {
               "pinyin_analyzer" : {
                   "tokenizer" : "my_pinyin"
                   }
           },
           "tokenizer" : {
               "my_pinyin" : {
                   "type" : "pinyin",
                   "keep_first_letter":true,
                   "keep_separate_first_letter" : true,
                   "keep_full_pinyin" : true,
                   "keep_original" : false,
                   "limit_first_letter_length" : 16,
                   "lowercase" : true
               }
           }
       }
   }
}

 

    打开索引:POST mib_tv_appstore_app_info/_open

 

    ②:创建映射

      方式1:使用多字段方式(在字段中定义多字段使用不同的方式索引,使用方式,name.pinyin)

POST /my_index/_mapping 
{
  "properties": {
      "app_name": {
          "type": "keyword",
          "fields": { // 在字段name下定义多字段pinyin,查询使用 name.pinyin
              "pinyin": {
                  "type": "text",
                  "store": false,
                  "term_vector": "with_offsets",
                  "analyzer": "pinyin_analyzer",
                  "boost": 10
              }
          }
      }
  }
}

 

      查询:

GET /my_index/_search
{
  "query": {
    "match_phrase": {
      "name.pinyin": "liudeh"
    }
  }
}

 

    方式2:定义一个新的字段

    TODO

 

 

  3、测试分析器

GET /my_index/_analyze
{
  "text": ["电视商城"],
  "analyzer": "pinyin_analyzer"
}

    结果:

{
  "tokens" : [
    {
      "token" : "dian",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "电视商城",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "dssc",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "shi",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "shang",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "cheng",
      "start_offset" : 0,
      "end_offset" : 0,
      "type" : "word",
      "position" : 3
    }
  ]
}
View Code

 

   索引配置选项:

    ①:keep_first_letter:when this option enabled, eg: 刘德华>ldh, default: true

    ②:keep_separate_first_letter:如果开启这个选项,将会对拼音的首字母做分隔。eg: 刘德华>l,d,h, default: false

      注意:查询结果将会很模糊 query result maybe too fuzziness due to term too frequency

    ③:limit_first_letter_length:设置首字母组合的最大长度,默认16

    ④:keep_full_pinyin:when this option enabled, eg: 刘德华> [liu,de,hua], default: true

    ⑤:keep_joined_full_pinyin:when this option enabled, eg: 刘德华> [liudehua], default: false

    ⑥:keep_none_chinese:keep non chinese letter or number in result, default: true

    ⑦:keep_none_chinese_together:保持非中文字符不拆分(keep non chinese letter together)default: true, eg: DJ音乐家 -> DJ,yin,yue,jia, when set to false, eg: DJ音乐家 -> D,J,yin,yue,jia, NOTE: keep_none_chinese should be enabled first

    ⑧:keep_none_chinese_in_first_letter:保持非中文字符在首字母分词中(keep non Chinese letters in first letter)eg: 刘德华AT2016->ldhat2016, default: true

    ⑨:keep_none_chinese_in_joined_full_pinyin:保持非中文字符在拼音全拼中(keep non Chinese letters in joined full pinyin)eg: 刘德华2016->liudehua2016, default: false

    ⑩:none_chinese_pinyin_tokenize:break non chinese letters into separate pinyin term if they are pinyin, default: true, eg: liudehuaalibaba13zhuanghan -> liu,de,hua,a,li,ba,ba,13,zhuang,han, NOTE: keep_none_chinese and keep_none_chinese_together should be enabled first

    ⑪:keep_original:when this option enabled, will keep original input as well, default: false

    ⑫:lowercase:lowercase non Chinese letters, default: true

    ⑭:trim_whitespace:default: true

    ⑮:remove_duplicated_term:when this option enabled, duplicated term will be removed to save index, eg: de的>de, default: false, NOTE: position related query maybe influenced

    ⑯:ignore_pinyin_offset:after 6.0, offset is strictly constrained, overlapped tokens are not allowed, with this parameter, overlapped token will allowed by ignore offset, please note, all position related query or highlight will become incorrect, you should use multi fields and specify different settings for different query purpose. if you need offset, please set it to false. default: true.

 

 

  

 

END.

posted @ 2022-01-06 17:11  杨岂  阅读(269)  评论(0编辑  收藏  举报