Elasticsearch分词器

阅读说明:
1.如果有排版格式问题,请移步https://www.yuque.com/mrhuang-ire4d/oufb8x/gmzl30v8ofqg3ua3?singleDoc# 《elasticsearch分词》,选择宽屏模式效果更佳。
2.本文为原创文章,转发请注明出处。

在建立倒排索引之前,先要分词器对文档数据进行处理。分析器是用于将文本数据划分为一系列的单词(或称之为词项、tokens)的组件。一个分析器包含以下三个部分:

  • 字符过滤器(Character filters)-使用字符过滤器转变字符,比如去除HTML标签,将数字转换为文字, 将特殊符号转换成文本等;
  • 分词器(Tokenizer)-将文本按照规则切分为单个或多个分词;
  • 分词过滤器(Token filters)-对分词进一步加工。比如转为小写,停滞词过滤等;

然后eleasticsearch搜索引擎Lucene对分词建立倒排索引,只有text类型才支持分词。


image.png

eleasticsearch内部自带了多个分析器,还可以自定义分析器。对于中文,有专业的第三方分析器比如IKAnalyzer等。

通常,搜索和索引共用分析器,以确保查询中的分词与反向索引中的分词具有相同的格式。也支持索引和查询使用不同的分析器满足个性化要求。
● analyzer:索引分析器,包含停用词参数。分词中包含停用词;
● search_analyzer: 指定非短语查询分词器,分词中删除停用词;
● search_quote_analyzer: 指定短语查询分词器,分词中包含停用词;

内置分析器

Standard Analyzer

默认分词器, 按Unicode文本分割算法拆分 , 转化为小写 , 支持中文(但是中文按照每个文字拆分,没啥意义)

示例

POST _analyze
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog's, bone ]

Standard Analyzer配置

参数 说明
max_token_length 分词最大长度,默认255。
stopwords 自定义停滞词。例如_english_,或一个停滞词数组, 默认_english_。
stopwords_path 包含停滞词的文件的路径,路径相对于Elasticsearch的config目录。

自定义配置示例

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_english_analyzer": {
          "type": "standard",
          "max_token_length": 5,
          "stopwords": "_english_"
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_english_analyzer",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ 2, quick, brown, foxes, jumpe, d, over, lazy, dog's, bone ]

Simple Analyzer

遇到非字母就切分,并且转化为小写。

示例

POST _analyze
{
  "analyzer": "simple",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ the, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ]

Stop Analyzer

在simple的基础上, 删除停滞词(停止词是指常见而无意义的词汇比如a, an, and, are, as, at, be, but, by, for, if, in, into, is, it, no, not, of, on, or, such, that, the, their, then, there, these, they, this, to, was, will, with),默认使用 stop token filter 的_english_预定义。

示例

POST _analyze
{
  "analyzer": "stop",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ quick, brown, foxes, jumped, over, lazy, dog, s, bone ]

Stop Analyzer 配置

参数 说明
stopwords 自定义停滞词。例如_english_,或一个停滞词数组, 默认_english_。
stopwords_path 包含停滞词的文件的路径,路径相对于Elasticsearch的config目录。

自定义配置示例

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_stop_analyzer": {
          "type": "stop",
          "stopwords": ["the", "over"]
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_stop_analyzer",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ quick, brown, foxes, jumped, lazy, dog, s, bone ]

Whitespace Analyzer

特点:遇到空格的时候会进行分词 , 不会转小写。
示例:

POST _analyze
{
    "analyzer": "whitespace",
    "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ The, 2, QUICK, Brown-Foxes, jumped, over, the, lazy, dog's, bone. ]

Patter Analyzer

按照正则表示式去切分,默认为\W+, 并且默认会转为小写。

示例

POST _analyze
{
  "analyzer": "pattern",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ]

Patter Analyzer配置

参数 说明
pattern 正则表达式,默认\W+。
flags Java正则表达式flags,多个用|分离,例如"CASE_INSENSITIVE | COMMENTS"。
lowercase 是否小写。默认true。
stopwords 预定义停滞词列表,例如_english_, 或一个停滞词数组,默认_none_。
stopwords_path 包含停滞词的文件的路径。

自定义配置示例

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_email_analyzer": {
          "type":      "pattern",
          "pattern":   "\\W|_", 
          "lowercase": true
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_email_analyzer",
  "text": "John_Smith@foo-bar.com"
}

分词结果:[ john, smith, foo, bar, com ]

Keyword Analyzer

特点:不分词 直接将输入当做输出

示例

POST _analyze
{
  "analyzer": "keyword",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

分词结果:[ The 2 QUICK Brown-Foxes jumped over the lazy dog's bone. ]

Fingerprint Analyzer

实现了指纹识别算法
对输入文本小写,规范化删掉扩展符,排序,去重,连接处理成单个分词。如果配置了停滞词列表,停滞词也将被删除。

示例

POST _analyze
{
  "analyzer": "fingerprint",
  "text": "Yes yes, Gödel said this sentence is consistent and."
}

分词结果:[ and consistent godel is said sentence this yes ]

Language Analyzers

针对特殊语言专门的分词器。这里不做详细介绍,后面有针对中文讲解中文分词器。

自定义分析器

当内置分析器不能满足您的需求时,您可以创建一个自定义分析器。一个自定义分词器由零个或多个char filters, 一个 Tokenizer 和零个或多个 token filters 组成。elasticsearch已经内置了多个字符过滤器,分词器和分词过滤器。

字符过滤器(Character Filters)

  • HTML Strip Character Filter: 从输入文本中移除HTML元素。比如<p>Hello World</p> 被处理为 Hello World,简写为html_strip。
  • Mapping Character Filter:通过一个预定义的映射关系,将指定的字符或字符串替换为其他字符或字符串。例如,你可以定义一个规则将 "&" 替换为 "and"。简写为mapping.
  • Pattern Replace Character Filter:使用正则表达式匹配和替换字符, 简写为pattern_replace。

HTML Strip Character Filter示例

GET /_analyze
{
  "tokenizer": "keyword",
  "char_filter": [
    "html_strip"
  ],
  "text": "<p>I&apos;m so <b>happy</b>!</p>"
}

分词结果:[ \nI'm so happy!\n ]

Mapping Character Filter示例

GET /_analyze
{
  "tokenizer": "keyword",
  "char_filter": [
    {
      "type": "mapping",
      "mappings": [
        "٠ => 0",
        "١ => 1",
        "٢ => 2",
        "٣ => 3",
        "٤ => 4",
        "٥ => 5",
        "٦ => 6",
        "٧ => 7",
        "٨ => 8",
        "٩ => 9"
      ]
    }
  ],
  "text": "My license plate is ٢٥٠١٥"
}

分词结果:[ My license plate is 25015 ]

Pattern Replace Character Filte示例

GET /_analyze
{
  "tokenizer": "keyword",
  "char_filter": [
    {
      "type": "pattern_replace",
      "pattern": "(\\d+)-(?=\\d)",
          "replacement": "$1_"
    }
  ],
  "text": "My credit card is 123-456-789"
}

分词结果:[My credit card is 123_456_789]

分词器(Tokenizer)

在内置分词器部分已经详细讲过了。

分词过滤器(Token Filters)

系统已经提供了多个分词过滤器,完整请参考Token filter reference | Elasticsearch Guide [7.7] | Elastic

  • Lowercase token filter: 转换为小写,简称为lowercase.
  • Stop token filter:移除停顿词,简称为stop.

Lowercase token filter示例

GET _analyze
{
  "tokenizer" : "standard",
  "filter" : ["lowercase"],
  "text" : "THE Quick FoX JUMPs"
}

分词结果:[ the, quick, fox, jumps ]

Stop token filter示例

GET /_analyze
{
  "tokenizer": "standard",
  "filter": [ "stop" ],
  "text": "a quick fox jumps over the lazy dog"
}

分词结果:[ quick, fox, jumps, over, lazy, dog ]

自定义分析器示例

下面有一个完整的自定义分析器示例,包含字符过滤器,分词器和分词过滤器。

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_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_"
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "I'm a :) person, and you?"
}


分词结果:[ i'm, _happy_, person, you ]

中文分词器 IKAnalyzer

IKAnalyzer提供两种分词:
ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;
ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。

示例

//创建索引
XPUT /index

//映射配置
POST /index/_mapping -H 'Content-Type:application/json' -d'
{
        "properties": {
            "content": {
                "type": "text",
                "analyzer": "ik_max_word",
                "search_analyzer": "ik_smart"
            }
        }

}

//写入数据
POST /index/_create/1 
{"content":"美国留给伊拉克的是个烂摊子吗"}

POST /index/_create/2
{"content":"公安部:各地校车将享最高路权"}

POST /index/_create/2
{"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"}

POST /index/_create/2
{"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"}

//查询含有中国的数据
POST /index/_search
{
    "query" : { "match" : { "content" : "中国" }},
    "highlight" : {
        "pre_tags" : ["<tag1>", "<tag2>"],
        "post_tags" : ["</tag1>", "</tag2>"],
        "fields" : {
            "content" : {}
        }
    }
}

返回结果:

{"took":14,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":2,"max_score":2,"hits":[{"_index":"index","_type":"fulltext","_id":"4","_score":2,"_source":{"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"},"highlight":{"content":["<tag1>中国</tag1>驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首 "]}},{"_index":"index","_type":"fulltext","_id":"3","_score":2,"_source":{"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"},"highlight":{"content":["均每天扣1艘<tag1>中国</tag1>渔船 "]}}]}}

词库配置

IKAnalyzer已经内置了词库,在目录{ik_path}/config下。

  • main.dic:主词库。
  • stopword.dic:英文停用词,不会建立在倒排索引中。
  • quantifier.dic:特殊词库:计量单位等。
  • suffix.dic:特殊词库:行政单位。
  • surname.dic:特殊词库:百家姓。
  • preposition:特殊词库:语气词。

当然,也支持用户自定义词库,在{ik_path}/config目录下添加自定义词库文件,要求每行一个词并且UTF8 编码,然后修改文件{ik_path}/config/IKAnalyzer.cfg.xml, 添加自定义词库位置,重启es。

<?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"></entry>
    <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords"></entry>
    <!--用户可以在这里配置远程扩展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry> -->
    <!--用户可以在这里配置远程扩展停止词字典-->
    <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

参考:

[1].https://www.elastic.co/guide/en/elasticsearch/reference/7.7/analysis-analyzers.html
[2].https://mp.weixin.qq.com/s?__biz=Mzg4Nzc3NjkzOA==&mid=2247485544&idx=1&sn=cfa20adbb5c7328ea0cab85966d95c02&chksm=cf847badf8f3f2bbefd1b9e893cccf10a24c2a83f8052b613c62c999566e4c8616fded236552#rd

[3].https://zhuanlan.zhihu.com/p/580356194

[4].https://github.com/medcl/elasticsearch-analysis-ik
[5].https://www.elastic.co/guide/en/elasticsearch/reference/7.7/analysis-charfilters.html
[6].https://www.elastic.co/guide/en/elasticsearch/reference/7.7/analysis-tokenizers.html
[7].https://www.elastic.co/guide/en/elasticsearch/reference/7.7/analysis-tokenfilters.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容