美文网首页
ElasticSearch核心之——分词

ElasticSearch核心之——分词

作者: moutory | 来源:发表于2021-01-30 22:43 被阅读0次

    前言

    我们知道ElasticSearch(简称ES)底层的搜索使用的是倒排索引依赖于分词器的实现,那么分词器的规则可以如何制定、ES中都提供了哪些常用的分词器给我们去使用呢?本文将围绕分词器的使用和细节进行讲解,希望能够对想要了解ES分词器的小伙伴们一个参考。

    一、说在前面的概念

    (一)分词

    分词是将文本转换成一系列单词的过程,也可以叫做文本分析,在ES中被称为Analysis。其实在日常生活中,分词这个概念我们应该并不陌生,比如我们使用百度/谷歌搜索引擎进行检索的时候,我们常常可以发现,我们输入的一段句子会被分割成不同的关键词关联查询。
    以“windows打开控制面板命令”为例子,我们在百度中进行搜索,会发现它被分割为windows控制面板命令等关键字来查询。

    image.png
    (二)分词器

    对语句进行分词的前提是定义了分词的规则。ES中为我们提供了许多功能强大、场景丰富的分词器组件,英文是Analyzer,它的组成如下:

    • Character Filter
      -针对原始的文本进行处理,比如去除html标记
    • Tokenizer
      -将原始的文本按照一定的规则切分为单词
    • Token Filter
      -针对tokenizer处理的单词进行再加工,比如转小写、删除或新增等处理

    我们可以看到分词器可以由三种组件组成,原始的数据流从Character Filter -> Tokenizer -> Token Filter一路下来,可以一步步地去除多余的数据再进去分割存储(输出)。

    二、分词器的API

    (一)简单的使用分词器

    ES给我们提供了一个测试分词的API接口,方便验证分词效果,在这个API中我们可以指定使用的分词器和索引来源,还可以使用自定义的分词器进行查看。

    POST _analyze
    {
      "analyzer": "standard",
      "text": [
          "hello es"
        ]
    }
    

    执行后结果如下:


    image.png

    上面的例子中,我们使用的是默认的分词器,我们也可以自定义分词器来进行使用

    POST _analyze
    {
      "tokenizer": "standard",
      "filter": ["lowercase"],
      "text": ["Hello World ElasticSearch"]
    }
    
    image.png
    (二)ES中自带的分词器
    1. Standard 标准分词器

    Standard是ES的默认分词器,具备按词切分、支持多语言;小写处理等特点。其具体组成如下图:

    standard分词器的组成
    POST _analyze
    {
      "analyzer": "standard",
      "text": ["The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."]
    }
    
    image.png
    2. Simple Analyzer 简单分词器

    简单分词器有着按照非字母切分、小写处理的特点,其具体组成如下图:


    image.png
    POST _analyze
    {
      "analyzer": "simple",
      "text": ["The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."]
    }
    
    image.png
    3. Whitespace Analyzer 空格分词器

    这个分词器很好理解,就是将文本根据空格进行分词。其组成如下图


    Whitespace Analyzer 空格分词器
    POST _analyze
    {
      "analyzer": "whitespace",
      "text": ["The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."]
    }
    
    
    image.png
    4. Stop Analyzer 语气助词分词器

    Stop Word指的是语气助词等修饰性的词语,比如thean等等,其组成如下图:

    Stop Analyzer分词器
    POST _analyze
    {
      "analyzer": "stop",
      "text": ["The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."]
    }
    
    响应结果
    5. Keyword Analyzer 关键字分词器

    Keyword分词器是一个比较特殊的存在,它不会对输入的句子进行分词,而是直接将输入作为一个单词输出,也就是说会将输入看成是一个整体。其组成如下:


    keyword分词器
    POST _analyze
    {
      "analyzer": "keyword",
      "text": ["The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."]
    }
    
    image.png
    6. Pattern Analyzer 正则分词器

    正则分词器很好理解,就是根据我们提供的正则表达式来进行分词,默认会按照 \W+ ,即非字词的符号作为分隔符。其组成如下:

    Pattern分词器
    POST _analyze
    {
      "analyzer": "pattern",
      "text": ["The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."]
    }
    
    响应结果
    7. Langueage Analyzer 多语言分词器

    多语言分词器提供了30+种常见语言的分词器
    诸如:arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english, estonian, finnish, french, galician, german, greek, hindi, hungarian, indonesian, irish, italian, latvian, lithuanian, norwegian, persian, portuguese, romanian, russian, sorani, spanish, swedish, turkish, thai.
    (详细用法可点击具体的语言,通过超链接进入es官网查看)

    (三)中文分词器

    上述的分词都是基于英文来进行分词的,对于中文而言,并不能完全适用。中文分词是指将一个汉字序列切分成一个个单独的词,在英文中,单词之间是通过空格作为自然分隔符,汉字中没有一个形式上的分词符。
    同时,汉字中存在着一词多义,一词多性(可做动词也可做名词),比如:"乒乓 / 球拍 / 卖完了" 和“乒乓球 / 拍卖 / 完了”。同样的一句话可以有多种分词方式,所以中文分词的难度较大,往往需要自己根据实际情况进行定义。常用的中文分词器有 ik分词器jieba分词器。

    三、自定义分词器

    当ES提供的分词器不能满足我们的分词需要的时候,我们可以通过自定义分词器来满足我们的工作需要,下面我们就从ES分词器的各个组件来进行自定义分词的测试吧。

    (一)Character Filter 字符过滤器

    我们知道最先到达分词器的组件是Character Filter,他会在 Tokenizer 之前对文本进行处理,比如增加、删除、或替换字符等。
    ES中自带的Character Filter有HTML Strip(去除html标签和转换html实体)、Mapping(进行字符替换等操作)、Pattern Replace(进行正则字符替换)。

    POST _analyze
    {
      "tokenizer": "keyword",
      "char_filter": ["html_strip"],
      "text": ["<p>I&apos;m so <b>happy</b>!</p>"]
    }
    
    image.png
    (二)Tokenizer 字符切分者

    Tokenizer会将原始文本(此处是指已经经过char_filter处理过的文本)按照一定的规则切分为单词,自带的Tokenizer如下:

    Tokenizer 功能
    standard 按照单词进行分割
    letter 按照非字符类进行分割
    whitespace 按照空格进行分割
    UAX URL Email 按照standard分割,但不会分割邮箱和url
    NGram和Edge NGram 连词分割
    Path Hierarchy 按照文件路径进行切割
    POST _analyze
    {
      "tokenizer": "uax_url_email",
      "text": ["his email is 123123@123.com"]
    }
    
    UAX URL Email切分者测试
    (三)Token Filter

    Token Filter会对 tokenizer输出的单词(term)进行增加、删除和修改等操作
    自带的Token Filter如下:

    token filter 功能
    lowercase 将所有的term转换为小写
    stop 删除stop words
    NGram和Edge NGram 连词分割
    Synonym 添加近义词的term
    POST _analyze
    {
      "tokenizer": "standard",
      "text": ["a Hello,Word!"],
      "filter": [
          "stop",
          "lowercase",
          {
            "type": "ngram",
            "min_gram": 3,
            "max_gram": 4
          }
        ]
    }
    
    token filter测试结果
    (四)自定义分词的API

    通过上面的介绍,我们可以知道分词器的三个组件的使用方法,下面我们就来学习一下如何定义一个自己的分词器吧。
    分词器的使用需要在索引的配置中设定,如下所示:

    PUT index_test
    {
      "settings": {
        "analysis": {
          "char_filter": {},
          "tokenizer": {},
          "filter": {},
          "analyzer": {}
        }
      }
    }
    

    比如我们要自定义这样结构的一个分词器:


    自定义分词器

    具体的定义语句如下:

    PUT index_test
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_custom_analyzer": {
              "type": "custom",
              "char_filter": ["html_strip"],
              "tokenizer": "standard",
              "filter": [
                  "lowercase",
                  "asciifolding"
                ]
            }
          }
        }
      }
    }
    
    自定义分词器结果测试

    我们再来举一个例子:


    自定义分词器2

    想要定义这样一个分词器,我们的建分词器语句为:

    PUT /index_test
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_coustom_analyzer": {
              "type": "custom",
              "char_filter": [
                "emoticons"
              ],
              "tokenizer": "punctuation",
              "filter": [
                "lowercase",
                "english_stop"
              ]
            }
          },
          "tokenizer": {
            "punctuation": {
              "type": "pattern",
              "pattern": "[ .!,?]"
            }
          },
          "char_filter": {
            "emoticons": {
              "type": "mapping",
              "mappings": [
                ":) => _happy_",
                ":( => _sad_"
              ]
            }
          },
          "filter": {
            "english_stop": {
              "type": "stop",
              "stopwords": "_english_"
            }
          }
        }
      }
    }
    
    自定义分词器2结果分析

    四、分词的使用说明

    对于ES分词的使用,一共有两个时机,一个是创建文档和更新文档(Index time)时,会对相应的文档进行分词处理;第二是查询时,会对查询语句进行分词。

    • 索引时分词
      索引时分词是通过配置Index Mapping 中每个字段的analyzer属性实现的
    PUT /index_test
    {
      "mappings": {
        "properties": {
          "title": {
            "type": "text",
            "analyzer": "standard" # 为字段指定analyzer
          }
        }
      }
    }
    
    • 查询时分词
      查询时分词可以有两种形式,分别是查询的时候通过analyzer指定分词器以及通过index mapping设置search_analyzer实现
      查询时分词的两种形式
      我们可以发现,在创建index的时候也可以定义查询时分词,一般来说,如果在创建索引的时候定义了查询时使用的分词器,那么我们在执行查询的过程中,也是要使用相同的分词器,否则会出现无法匹配的情况!!!

    五、使用分词的建议

    1、明确字段是否需要分词,不需要分词的字段就将type设置为keyword,可以节省空间和提高写性能
    2、对于不太清楚的分词效果,可以自己动手调试或者查看一下官方文档,个人觉得官方文档还是写的比较全面的。
    官方文档链接如下:
    https://www.elastic.co/guide/en/elasticsearch/reference/7.x/analysis-index-search-time.html
    (自己根据实际版本看对应的文档)

    相关文章

      网友评论

          本文标题:ElasticSearch核心之——分词

          本文链接:https://www.haomeiwen.com/subject/ojyxtltx.html