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

3次阅读

共计 9736 个字符,预计需要花费 25 分钟才能阅读完成。

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

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

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

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

转载请注明出处!

正文完
 0