关于java:9种ElasticSearch分词器详解一文get-博学谷狂野架构师

ElasticSearch 分词器

  • 作者: 博学谷狂野架构师
  • 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>"  # 输出的文本
}

指定分词器

应用中央

分词器的应用中央有两个:

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

如果设置手动设置了分词器,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"
}

能够看出是依照空格、非字母的形式对输出的文本进行了转换,比方对 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"
}

空白分词器(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"
}

电子邮件分词器(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"
}

可配置项

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"
}

会发现前后内容基本没有产生扭转,这也是这个分词器的作用,有些时候咱们针对一个须要分词查问的字段进行查问的时候,可能并不心愿查问条件被分词,这个时候就能够应用这个分词器,整个查问条件作为一个关键词应用

正则分词器(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"
}

可配置项

正则分词器有以下的选项

选项 形容
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"
}

可配置项
选项 形容
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"
}

自定义分词器

当内置的分词器无奈满足需要时,能够创立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"
}

中文分词器

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": "传智教育的教学质量是杠杠的"
}

ik_max_word

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

自定义词库

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

问题形容

例如咱们输出“传智教育的教学质量是杠杠的”,然而分词器会把“传智教育”进行拆开,分为了“传”,“智”,“教育”,但咱们心愿的是“传智教育”能够不被拆开

解决方案

对于以上的问题,咱们只须要将本人要保留的词,加到咱们的分词器的字典中即可

编辑字典内容

进入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": "传智教育的教学质量是杠杠的"
}

能够发现,当初咱们的词汇”传智教育”就不会被拆开了,达到咱们想要的成果了

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

如果本文对您有帮忙,欢送关注点赞;如果您有任何倡议也可留言评论私信,您的反对是我保持创作的能源。

转载请注明出处!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理