美文网首页
【9种】ElasticSearch分词器详解,一文get!!!|

【9种】ElasticSearch分词器详解,一文get!!!|

作者: 博学谷狂野架构师 | 来源:发表于2023-05-07 16:22 被阅读0次

    ElasticSearch 分词器

    img
    • 作者: 博学谷狂野架构师
    • GitHub:GitHub地址 (有我精心准备的130本电子书PDF)

    只分享干货、不吹水,让我们一起加油!😄

    概述

    分词器的主要作用将用户输入的一段文本,按照一定逻辑,分析成多个词语的一种工具

    什么是分词器

    顾名思义,文本分析就是把全文本转换成一系列单词(term/token)的过程,也叫分词。在 ES 中,Analysis 是通过分词器(Analyzer) 来实现的,可使用 ES 内置的分析器或者按需定制化分析器。

    举一个分词简单的例子:比如你输入 Mastering Elasticsearch,会自动帮你分成两个单词,一个是 mastering,另一个是 elasticsearch,可以看出单词也被转化成了小写的。

    图片

    分词器的构成

    分词器是专门处理分词的组件,分词器由以下三部分组成:

    组成部分
    character filter

    接收原字符流,通过添加、删除或者替换操作改变原字符流

    例如:去除文本中的html标签,或者将罗马数字转换成阿拉伯数字等。一个字符过滤器可以有零个或者多个

    tokenizer

    简单的说就是将一整段文本拆分成一个个的词。

    例如拆分英文,通过空格能将句子拆分成一个个的词,但是对于中文来说,无法使用这种方式来实现。在一个分词器中,有且只有一个tokenizeer

    token filters

    将切分的单词添加、删除或者改变

    例如将所有英文单词小写,或者将英文中的停词a删除等,在token filters中,不允许将token(分出的词)position或者offset改变。同时,在一个分词器中,可以有零个或者多个token filters.

    分词顺序
    图片

    同时 Analyzer 三个部分也是有顺序的,从图中可以看出,从上到下依次经过 Character FiltersTokenizer 以及 Token Filters,这个顺序比较好理解,一个文本进来肯定要先对文本数据进行处理,再去分词,最后对分词的结果进行过滤。

    索引和搜索分词

    文本分词会发生在两个地方:

    • 创建索引:当索引文档字符类型为text时,在建立索引时将会对该字段进行分词。
    • 搜索:当对一个text类型的字段进行全文检索时,会对用户输入的文本进行分词。
    配置分词器

    默认ES使用standard analyzer,如果默认的分词器无法符合你的要求,可以自己配置

    分词器测试

    可以通过_analyzerAPI来测试分词的效果。

    COPY# 过滤html 标签
    POST _analyze
    {
        "tokenizer":"keyword", #原样输出
        "char_filter":["html_strip"], # 过滤html标签
        "text":"<b>hello world<b>"  # 输入的文本
    }
    
    image-20220808135231869

    指定分词器

    使用地方

    分词器的使用地方有两个:

    • 创建索引时
    • 进行搜索时
    创建索引时指定分词器

    如果设置手动设置了分词器,ES将按照下面顺序来确定使用哪个分词器:

    • 先判断字段是否有设置分词器,如果有,则使用字段属性上的分词器设置
    • 如果设置了analysis.analyzer.default,则使用该设置的分词器
    • 如果上面两个都未设置,则使用默认的standard分词器
    字段指定分词器

    为title属性指定分词器

    COPYPUT my_index
    {
      "mappings": {
        "properties": {
          "title":{
            "type":"text",
            "analyzer": "whitespace"
          }
        }
      }
    }
    
    设置默认分词器
    COPYPUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "default":{
              "type":"simple"
            }
          }
        }
      }
    }
    
    搜索时如何确定分词器

    在搜索时,通过下面参数依次检查搜索时使用的分词器:

    • 搜索时指定analyzer参数
    • 创建mapping时指定字段的search_analyzer属性
    • 创建索引时指定settinganalysis.analyzer.default_search
    • 查看创建索引时字段指定的analyzer属性
    • 如果上面几种都未设置,则使用默认的standard分词器。
    指定analyzer

    搜索时指定analyzer查询参数

    COPYGET my_index/_search
    {
      "query": {
        "match": {
          "message": {
            "query": "Quick foxes",
            "analyzer": "stop"
          }
        }
      }
    }
    
    指定字段analyzer
    COPYPUT my_index
    {
      "mappings": {
        "properties": {
          "title":{
            "type":"text",
            "analyzer": "whitespace",
            "search_analyzer": "simple"
          }
        }
      }
    }
    
    指定默认default_seach
    COPYPUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "default":{
              "type":"simple"
            },
            "default_seach":{
              "type":"whitespace"
            }
          }
        }
      }
    }
    

    内置分词器

    es在索引文档时,会通过各种类型 Analyzer 对text类型字段做分析,

    不同的 Analyzer 会有不同的分词结果,内置的分词器有以下几种,基本上内置的 Analyzer 包括 Language Analyzers 在内,对中文的分词都不够友好,中文分词需要安装其它 Analyzer

    分析器 描述 分词对象 结果
    standard 标准分析器是默认的分析器,如果没有指定,则使用该分析器。它提供了基于文法的标记化(基于 Unicode 文本分割算法,如 Unicode 标准附件 # 29所规定) ,并且对大多数语言都有效。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog’s, bone ]
    simple 简单分析器将文本分解为任何非字母字符的标记,如数字、空格、连字符和撇号、放弃非字母字符,并将大写字母更改为小写字母。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ the, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ]
    whitespace 空格分析器在遇到空白字符时将文本分解为术语 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ The, 2, QUICK, Brown-Foxes, jumped, over, the, lazy, dog’s, bone. ]
    stop 停止分析器与简单分析器相同,但增加了删除停止字的支持。默认使用的是 _english_ 停止词。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ quick, brown, foxes, jumped, over, lazy, dog, s, bone ]
    keyword 不分词,把整个字段当做一个整体返回 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone.]
    pattern 模式分析器使用正则表达式将文本拆分为术语。正则表达式应该匹配令牌分隔符,而不是令牌本身。正则表达式默认为 w+ (或所有非单词字符)。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ]
    多种西语系 arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english等等 一组旨在分析特定语言文本的分析程序。

    中文扩展分析器

    中文分词器最简单的是ik分词器,还有jieba分词,哈工大分词器等

    分词器 描述 分词对象 结果
    ik_smart ik分词器中的简单分词器,支持自定义字典,远程字典 学如逆水行舟,不进则退 [学如逆水行舟,不进则退]
    ik_max_word ik_分词器的全量分词器,支持自定义字典,远程字典 学如逆水行舟,不进则退 [学如逆水行舟,学如逆水,逆水行舟,逆水,行舟,不进则退,不进,则,退]

    词语分词

    标准分词器(Standard Tokenizer)

    根据standardUnicode文本分段算法的定义,将文本划分为多个单词边界的上的术语

    它是 ES 默认的分词器,它会对输入的文本按词的方式进行切分,切分好以后会进行转小写处理,默认的 stopwords 是关闭的

    图片
    使用案例

    下面使用 Kibana 看一下它是怎么样进行工作的

    原始内容
    COPYIn 2020, Java is the best language in the world.
    
    测试分词

    在 Kibana 的开发工具(Dev Tools)中指定 Analyzer 为 standard,并输入文本 In 2020, Java is the best language in the world.,然后我们运行一下:

    COPYGET _analyze
    {
      "text":"In 2020, Java is the best language in the world.",
      "analyzer": "standard"
    }
    
    image-20220808105014779

    可以看出是按照空格、非字母的方式对输入的文本进行了转换,比如对 Java 做了转小写,对一些停用词也没有去掉,比如 in,其中 token 为分词结果;start_offset 为起始偏移;end_offset 为结束偏移;position 为分词位置。

    可配置项
    选项 描述
    max_token_length 最大令牌长度。如果看到令牌超过此长度,则将其max_token_length间隔分割。默认为255。
    stopwords 预定义的停用词列表,例如english或包含停用词列表的数组。默认为none。
    stopwords_path 包含停用词的文件的路径。
    COPY{
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_english_analyzer": {
                        "type": "standard",
                        "max_token_length": 5,
                        "stopwords": "_english_"
                    }
                }
            }
        }
    }
    

    简单分词器(Letter Tokenizer)

    当simple分析器遇到非字母的字符时,它会将文本划分为多个术语,它小写所有术语,对于中文和亚洲很多国家的语言来说是无用的

    图片

    它只包括了 Lower CaseTokenizer,它会按照非字母切分非字母的会被去除,最后对切分好的做转小写处理,然后接着用刚才的输入文本,分词器换成 simple 来进行分词,运行结果如下:

    使用案例
    原始内容
    COPYIn 2020, Java is the best language in the world.
    
    测试分词
    COPYGET _analyze
    {
      "text":"In 2020, Java is the best language in the world.",
      "analyzer": "simple"
    }
    
    image-20220808105857762

    空白分词器(Whitespace Tokenizer)

    它非常简单,根据名称也可以看出是按照空格进行切分

    该whitespace分析仪将文本分为方面每当遇到任何空白字符,和上面的分词器不同,空白分词器默认并不会将内容转换为小写。

    图片
    使用案例
    原始内容
    COPYIn 2020, Java is the best language in the world.
    
    测试分词
    COPYGET _analyze
    {
      "text":"In 2020, Java is the best language in the world.",
      "analyzer": "whitespace"
    }
    
    image-20220808110235685

    电子邮件分词器(UAX URL Email Tokenizer)

    此分词器主要是针对email和url地址进行关键内容的标记。

    使用案例
    原始内容
    COPY"Email me at john.smith@global-international.com"
    
    测试分词
    COPYGET _analyze
    {
      "text":"Email me at john.smith@global-international.com",
      "tokenizer": "uax_url_email"
    }
    
    可配置项

    max_token_length最大令牌长度。如果看到令牌超过此长度,则将其max_token_length间隔分割。默认为255

    COPY{
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_english_analyzer": {
                        "type": "standard",
                        "max_token_length": 5
                    }
                }
            }
        }
    }
    

    经典分词器(Classic Tokenizer)

    可对首字母缩写词,公司名称,电子邮件地址和互联网主机名进行特殊处理,但是,这些规则并不总是有效,并且此关键词生成器不适用于英语以外的大多数其他语言

    特点
    • 它最多将标点符号拆分为单词,删除标点符号,但是,不带空格的点被认为是查询关键词的一部分
    • 此分词器可以将邮件地址和URL地址识别为查询的term(词条)
    使用案例
    原始内容
    COPY"The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
    
    测试分词
    COPYGET _analyze
    {
      "text":"The 2 QUICK Brown-Foxes jumped over the lazy dog's bone.",
      "analyzer": "classic"
    }
    
    image-20220808111755030
    可配置项

    max_token_length最大令牌长度。如果看到令牌超过此长度,则将其max_token_length间隔分割。默认为255。

    COPY{
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_analyzer": {
                        "tokenizer": "my_tokenizer"
                    }
                },
                "tokenizer": {
                    "my_tokenizer": {
                        "type": "classic",
                        "max_token_length": 5
                    }
                }
            }
        }
    }
    

    结构化文本分词

    关键词分词器(Keyword Tokenizer)

    它其实不做分词处理,只是将输入作为 Term 输出

    关键词分词器其实是执行了一个空操作的分析,它将任何输入的文本作为一个单一的关键词输出。

    图片
    使用案例
    原始内容
    COPY"In 2020, Java is the best language in the world."
    
    测试分词
    COPYGET _analyze
    {
      "text":"In 2020, Java is the best language in the world.",
      "analyzer": "keyword"
    }
    

    会发现前后内容根本没有发生改变,这也是这个分词器的作用,有些时候我们针对一个需要分词查询的字段进行查询的时候,可能并不希望查询条件被分词,这个时候就可以使用这个分词器,整个查询条件作为一个关键词使用

    image-20220808112235674

    正则分词器(Pattern Tokenizer)

    模式标记器使用 Java正则表达式。使用JAVA的正则表达式进行词语的拆分。

    它可以通过正则表达式的方式进行分词,默认是用 \W+ 进行分割的,也就是非字母的符合进行切分的。

    图片
    使用案例
    原始内容
    COPY"In 2020, Java is the best language in the world."
    
    测试分词
    COPYGET _analyze
    {
      "text":"In 2020, Java is the best language in the world.",
      "analyzer": "patter"
    }
    
    image-20220808112737629
    可配置项

    正则分词器有以下的选项

    选项 描述
    pattern 正则表达式
    flags 正则表达式标识
    lowercase 是否使用小写词汇
    stopwords 停止词的列表。
    stopwords_path 定义停止词文件的路径。
    COPY{
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_email_analyzer": {
                        "type": "pattern",
                        "pattern": "\\W|_",
                        "lowercase": true
                    }
                }
            }
        }
    }
    

    路径分词器(Path Tokenizer)

    可以对文件系统的路径样式的请求进行拆分,返回被拆分各个层级内容。

    使用案例
    原始内容
    COPY"/one/two/three"
    
    测试分词
    COPYGET _analyze
    {
      "text":"/one/two/three",
      "tokenizer":"path_hierarchy"
    }
    
    image-20220808113500717
    可配置项
    选项 描述
    delimiter 用作路径分隔符的字符
    replacement 用于定界符的可选替换字符
    buffer_size 单次读取到术语缓冲区中的字符数。默认为1024。术语缓冲区将以该大小增长,直到所有文本都被消耗完为止。建议不要更改此设置。
    reverse 正向还是反向获取关键词
    skip 要忽略的内容
    COPY{
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_analyzer": {
                        "tokenizer": "my_tokenizer"
                    }
                },
                "tokenizer": {
                    "my_tokenizer": {
                        "type": "path_hierarchy",
                        "delimiter": "-",
                        "replacement": "/",
                        "skip": 2
                    }
                }
            }
        }
    }
    

    语言分词(Language Analyzer)

    ES 为不同国家语言的输入提供了 Language Analyzer 分词器,在里面可以指定不同的语言

    支持语种

    支持如下语种:

    关键字 语种
    arabic 美 /ˈærəbɪk/ 阿拉伯语
    armenian 美 /ɑːrˈmiːniən/ 亚美尼亚语
    basque 美 /bæsk,bɑːsk/ 巴斯克语
    bengali 美 /beŋˈɡɑːli/ 孟加拉语
    brazilian 美 /brəˈzɪliən/ 巴西语
    bulgarian 美 /bʌlˈɡeriən/ 保加利亚语
    catalan 美 /ˈkætəlæn/ 加泰罗尼亚语
    cjk 中日韩统一表意文字
    czech 美 /tʃek/ 捷克语
    danish 美 /ˈdeɪnɪʃ/ 丹麦语
    dutch 美 /dʌtʃ/ 荷兰语
    english 美 /ˈɪŋɡlɪʃ/ 英语
    estonian 美 /eˈstoʊniən/ 爱沙尼亚语
    finnish 美 /ˈfɪnɪʃ/ 芬兰语
    french 美 /frentʃ/ 法语
    galician 美 /ɡəˈlɪʃn/ 加里西亚语
    german 美 /ˈdʒɜːrmən/ 德语
    greek 美 /ɡriːk/ 希腊语
    hindi 美 /ˈhɪndi/ 北印度语
    hungarian 美 /hʌŋˈɡeriən/ 匈牙利语
    indonesian 美 /ˌɪndəˈniːʒn/ 印度尼西亚语
    irish 美 /ˈaɪrɪʃ/ 爱尔兰语
    italian 美 /ɪˈtæliən/ 意大利语
    latvian 美 /ˈlætviən/ 拉脱维亚语
    lithuanian 美 /ˌlɪθuˈeɪniən/ 立陶宛语
    norwegian 美 /nɔːrˈwiːdʒən/ 挪威语
    persian /‘pɜːrʒən/ 波斯语
    portuguese 美 /ˌpɔːrtʃʊˈɡiːz/ 葡萄牙语
    romanian 美 /ro’menɪən/ 罗马尼亚语
    russian 美 /ˈrʌʃn/ 俄语
    sorani 索拉尼语
    spanish 美 /ˈspænɪʃ/ 西班牙语
    swedish 美 /ˈswiːdɪʃ/ 瑞典语
    turkish 美 /ˈtɜːrkɪʃ/ 土耳其语
    thai 美 /taɪ/ 泰语
    使用案例

    下面我们使用英语进行分析

    原始内容
    COPY"In 2020, Java is the best language in the world."
    
    测试分词
    COPYGET _analyze
    {
      "text":"In 2020, Java is the best language in the world.",
      "analyzer":"english"
    }
    
    image-20220808114216744

    自定义分词器

    当内置的分词器无法满足需求时,可以创建custom类型的分词器。

    配置参数
    参数 描述
    tokenizer 内置或定制的tokenizer.(必须)
    char_filter 内置或定制的char_filter(非必须)
    filter 内置或定制的token filter(非必须)
    position_increment_gap 当值为文本数组时,设置改值会在文本的中间插入假空隙。设置该属性,对与后面的查询会有影响。默认该值为100.
    创建索引

    上面的示例中定义了一个名为my_custom_analyzer的分词器

    该分词器的typecustomtokenizerstandardchar_filterhmtl_strip,filter定义了两个分别为:lowercaseasciifolding

    COPYPUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_custom_analyzer":{
              "type":"custom",
              "tokenizer":"standard",
              "char_filter":["html_strip"],
              "filter":["lowercase","asciifolding"]
            }
          }
        }
      }
    }
    
    使用案例
    原始内容
    COPYIs this <b>déjà vu</b>?
    
    测试分词
    COPYPOST my_index/_analyze
    {
      "text": "Is this <b>déjà vu</b>?",
      "analyzer": "my_custom_analyzer"
    }
    
    image-20220808140137712

    中文分词器

    IKAnalyzer

    IKAnalyzer是一个开源的,基于java的语言开发的轻量级的中文分词工具包

    从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本,在 2012 版本中,IK 实现了简单的分词歧义排除算法,标志着 IK 分词器从单纯的词典分词向模拟语义分词衍化

    使用IK分词器

    IK提供了两个分词算法:

    • ik_smart:最少切分。
    • ik_max_word:最细粒度划分。

    ik_smart

    使用案例
    原始内容
    COPY传智教育的教学质量是杠杠的
    
    测试分词
    COPYGET _analyze
    {
      "analyzer": "ik_smart",
      "text": "传智教育的教学质量是杠杠的"
    }
    
    image-20220808115450647

    ik_max_word

    使用案例
    原始内容
    COPY传智教育的教学质量是杠杠的
    
    测试分词
    COPYGET _analyze
    {
      "analyzer": "ik_max_word",
      "text": "传智教育的教学质量是杠杠的"
    }
    
    image-20220808115513668

    自定义词库

    我们在使用IK分词器时会发现其实有时候分词的效果也并不是我们所期待的

    问题描述

    例如我们输入“传智教育的教学质量是杠杠的”,但是分词器会把“传智教育”进行拆开,分为了“传”,“智”,“教育”,但我们希望的是“传智教育”可以不被拆开

    image-20220808115543696
    解决方案

    对于以上的问题,我们只需要将自己要保留的词,加到我们的分词器的字典中即可

    编辑字典内容

    进入elasticsearch目录plugins/ik/config中,创建我们自己的字典文件yixin.dic,并添加内容:

    COPYcd plugins/ik/config
    echo "传智教育" > custom.dic
    
    扩展字典

    进入我们的elasticsearch目录 :plugins/ik/config,打开IKAnalyzer.cfg.xml文件,进行如下配置:

    COPYvi IKAnalyzer.cfg.xml
    #增加如下内容
    <entry key="ext_dict">custom.dic</entry>
    
    再次测试

    重启ElasticSearch,再次使用kibana测试

    COPYGET _analyze
    {
      "analyzer": "ik_max_word",
      "text": "传智教育的教学质量是杠杠的"
    }
    

    可以发现,现在我们的词汇”传智教育”就不会被拆开了,达到我们想要的效果了

    image-20220808134046401

    本文由传智教育博学谷狂野架构师教研团队发布。

    如果本文对您有帮助,欢迎关注点赞;如果您有任何建议也可留言评论私信,您的支持是我坚持创作的动力。

    转载请注明出处!

    相关文章

      网友评论

          本文标题:【9种】ElasticSearch分词器详解,一文get!!!|

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