官网文档
https://www.elastic.co/guide/en/elasticsearch/reference/6.7/analysis.html

概要

文本分析是一个处理过程,他将一段文本(例如一封email或一句话)转化为一个个token或term(可以理解为词语或单词),然后将他们添加到倒排索引中用来查询。文本分析是由分析器执行的,可以是内置的也可以是每个索引自定义的。

索引时的分析

例如,在索引的时候,内置的 english 分析器,会将下面的句子进行转换:

“The QUICK brown foxes jumped over the lazy dog!”

转换为不同的token。它会将各token转化为小写,删除常用的停用词(“the”),将term简化为词根 (foxes → fox, jumped → jump, lazy → lazi)。最后,下面的term会被添加到倒排索引中:

[ quick, brown, fox, jump, over, lazi, dog ]

指定索引时候的分析器

在mapping中的任何 text 类型的字段可以指定它自己的分析器( analyzer ):

  1. curl -X PUT "localhost:9200/my_index?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "mappings": {
  4. "_doc": {
  5. "properties": {
  6. "title": {
  7. "type": "text",
  8. "analyzer": "standard"
  9. }
  10. }
  11. }
  12. }
  13. }
  14. '

在索引时,如果没有指定 analyzer ,它会寻找index settings中名称为default的analyzer。否则,默认使用standard analyzer

查询时的分析

在执行full text queries (如match query)时,相同的分析过程会应用在查询字符串上,将查询字符串的文本转换为与存储在倒排索引中相同形式的term。

例如,用户可能搜索:

“a quick fox”

它会被相同的english analyzer 分析为下面的term:

[ quick, fox ]

尽管查询信息中使用的确切单词在原始文本中没有出现(quick vs QUICK, fox vs foxes),但是因为原始文本和查询信息使用相同的analyzer,查询信息的term和倒排索引中原始文本的term完全匹配,这意味着这个查询会匹配我们的样例document。

指定查询时的分析器

通常在索引和查询时使用相同的analyzer,full text queries(如match query)会使用mapping查找每个字段使用的analyzer。

搜索某个特定字段而使用的analyzer(优先级)取决于:

  • 在query中指定的 analyzer
  • mapping参数 search_analyzer
  • mapping参数 analyzer
  • index settings参数 default_search
  • index settings参数 default
  • standard analyzer

    剖析分析器

    无论是内置的还是自定义的analyzer,只是一个包含了3个更低级的构建块:character filters, tokenizers, and token filters的包。

内置的analyzer将这些构建块预先打包到适合不同语言和文本类型的analyzer中。Elasticsearch还公开了各个构件块,以便他们可以组合起来定义新的自定义analyzer。

Character filters

character filter接收原始文本作为一个字符流,可以通过增加、删除、修改字符来转换改流。例如,一个character filter可以将印度-阿拉伯数字(٠‎١٢٣٤٥٦٧٨‎٩‎)转化为阿拉伯-拉丁数字(0123456789),或者从流中过滤像这样的HTML元素

一个analyzer可以拥有0或多个character filter,他们按顺序应用。

Tokenizer

tokenizer接收一个字符流,将其分解为单个的token(通常是单个的单词),并输出一个token流。例如,whitespace tokenizer当遇到空格时,会将文本分解为token。它会将文件”Quick brown fox!”转换为term[Quick, brown, fox!]。

tokenizer还负责记录每个term的顺序和位置,以及改term所表示的原单词的开始和结束字符的偏移量。

一个analyzer有且只有一个tokenizer。

Token filters

token filter接收token流,并且可以对其中的token进行增加、删除、修改。例如,lowercase token filter将所有的token转为小写,stop token filter可以从token流中删除像the的通用单词(停用词),synonym token filter将同义词引入token流。

token filter不允许修改任何token的位置和字符偏移量。

一个analyzer可有拥有0个或多个token filter,他们按顺序应用。

测试分析器

analyze API是一个无价的工具,可以查看analyzer产生的term。内置的analyzer(或者使用内置的tokenizer, token filters, character filters组合的)可以在请求正文中指定:

  1. curl -X POST "localhost:9200/_analyze?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "analyzer": "whitespace",
  4. "text": "The quick brown fox."
  5. }
  6. '
  7. curl -X POST "localhost:9200/_analyze?pretty" -H 'Content-Type: application/json' -d'
  8. {
  9. "tokenizer": "standard",
  10. "filter": [ "lowercase", "asciifolding" ],
  11. "text": "Is this déja vu?"
  12. }
  13. '

位置和字符偏移量 ** 从analyze API的输出看,analyzer不仅将单词转为term,还记录了term的顺序和相对位置(用于phrase queries or word proximity queries),每个term在原文中的开始和结束字符的偏移量(用于高亮查询)。

另外,在明确的index上执行analyze API时,custom analyzer可以被引用。

  1. curl -X PUT "localhost:9200/my_index?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "std_folded": {
  7. "type": "custom",
  8. "tokenizer": "standard",
  9. "filter": [
  10. "lowercase",
  11. "asciifolding"
  12. ]
  13. }
  14. }
  15. }
  16. },
  17. "mappings": {
  18. "_doc": {
  19. "properties": {
  20. "my_text": {
  21. "type": "text",
  22. "analyzer": "std_folded"
  23. }
  24. }
  25. }
  26. }
  27. }
  28. '
  29. curl -X GET "localhost:9200/my_index/_analyze?pretty" -H 'Content-Type: application/json' -d'
  30. {
  31. "analyzer": "std_folded",
  32. "text": "Is this déjà vu?"
  33. }
  34. '
  35. curl -X GET "localhost:9200/my_index/_analyze?pretty" -H 'Content-Type: application/json' -d'
  36. {
  37. "field": "my_text",
  38. "text": "Is this déjà vu?"
  39. }
  40. '

第6行 定义一个名为std_folded的custom analyzer
第22行 字段custom analyzer 使用了std_folded analyzer
第29、35行 引用这个analyzer(自定义的std_folded),analyze API必须指定索引名
第31行 通过名称引用analyzer
第37行 通过字段my_text引用analyzer

Analyzers

Elasticsearch提供了广泛的内置analyzer,可以无需更多设置再任意index中使用。

  • Standard Analyzer

standard analyzer按照Unicode文本分割算法,在单词边界上将文本分为term。他删除了大部分标点,小写term,且支持删除stop words。

  • Simple Analyzer

当遇到一个不是字母的字符时,simple analyzer将文本分为term。所有的term转为小写。

  • Whitespace Analyzer

当遇到空白字符时,whitespace analyzer将文本分为term。term不会转为小写。

  • Stop Analyzer

stop analyzer与simple analyzer相似,但是支持删除stop words。

  • Keyword Analyzer

keyword analyzer是一个“noop” analyzer,接收给定的任意文本,然后输出一个与文本完全相同的term。

  • Pattern Analyzer

pattern analyzer使用正则表达式将文本分割为term。它支持小写和停用词。

  • Language Analyzers

Elasticsearch提供了许多特定语言的analyzer,如英语好法语。

  • Fingerprint Analyzer

fingerprint analyzer是一个专门的analyzer,它可以创建指纹用于重复检查。

  • Custom Analyzer

如果没有发现你需要的合适的analyzer,你可以创建一个custom analyzer,它结合了适当的character filters, tokenizer, and token filters。

配置内置analyzer

内置analyzer可以不经过任何配置直接使用。然而,有些analyzer支持配置选项来改变行为。比如,standard analyzer可以通过配置支持一个stop words列表:

  1. curl -X PUT "localhost:9200/my_index?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "std_english": {
  7. "type": "standard",
  8. "stopwords": "_english_"
  9. }
  10. }
  11. }
  12. },
  13. "mappings": {
  14. "_doc": {
  15. "properties": {
  16. "my_text": {
  17. "type": "text",
  18. "analyzer": "standard",
  19. "fields": {
  20. "english": {
  21. "type": "text",
  22. "analyzer": "std_english"
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }
  29. }
  30. '
  31. curl -X POST "localhost:9200/my_index/_analyze?pretty" -H 'Content-Type: application/json' -d'
  32. {
  33. "field": "my_text",
  34. "text": "The old brown cow"
  35. }
  36. '
  37. curl -X POST "localhost:9200/my_index/_analyze?pretty" -H 'Content-Type: application/json' -d'
  38. {
  39. "field": "my_text.english",
  40. "text": "The old brown cow"
  41. }
  42. '

第7行 我们基于standard analyzer定义了std_english analyzer,但是将其配置为删除预定义的英语停用词列表。
第18、33行 字段my_text直接使用standard analyzer,没有任何配置。没有stop words会从该字段删除。产生的term:[ the, old, brown, cow ]
第22、39行 字段my_text.english使用std_english analyzer,因此英语stop words会被删除。产生的term:[ old, brown, cow ]

Standard Analyzer

standard analyzer是默认的analyzer,没有指定则使用它。提供了基于标记的语法(基于Unicode文本分割算法,如Unicode标准附件#29中指定的),并且适用于大多数语言。

输出样例

  1. curl -X POST "localhost:9200/_analyze?pretty" -H 'Content-Type: application/json' -d'
  2. {
  3. "analyzer": "standard",
  4. "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog\u0027s bone."
  5. }
  6. '

上面的句子会产生下面的term:

[ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog’s, bone ]

配置

standard analyzer接受下面的参数:

  • max_token_length token的最大长度。如果token超过了这个长度,他会以max_token_length间隔分割该token。默认255。
  • stopwords 一个如english预定义的stop words列表或者是一个包含stop words列表的数组。默认none
  • stopwords_path 一个包含stop words的文件的路径。

    配置样例

    在本例中,我们配置standard analyzer的max_token_length参数为5(出于演示的目的),且使用预定义的英语stop words列表。 ```shell curl -X PUT “localhost:9200/my_index?pretty” -H ‘Content-Type: application/json’ -d’ { “settings”: { “analysis”: {
    1. "analyzer": {
    2. "my_english_analyzer": {
    3. "type": "standard",
    4. "max_token_length": 5,
    5. "stopwords": "_english_"
    6. }
    7. }
    } } } ‘ curl -X POST “localhost:9200/my_index/_analyze?pretty” -H ‘Content-Type: application/json’ -d’ { “analyzer”: “my_english_analyzer”, “text”: “The 2 QUICK Brown-Foxes jumped over the lazy dog\u0027s bone.” } ‘
  1. 上面的样例产生了下面的term
  2. > [ 2, quick, brown, foxes, jumpe, d, over, lazy, dog's, bone ]
  3. <a name="NXU36"></a>
  4. ### 定义
  5. standard analyzer包含:
  6. - Tokenizer
  7. - Standard Tokenizer
  8. - Token Filters
  9. - Standard Token Filter
  10. - Lower Case Token Filter
  11. - Stop Token Filter (disabled by default)
  12. 如果你需要在配置参数之外自定义standard analyzer,你需要把它当做一个custom analyzer进行重建并且修改它,通常通过增加token filters。这里我们会重建内置的standard analyzer,你可以使用它作为起点:
  13. ```shell
  14. curl -X PUT "localhost:9200/standard_example?pretty" -H 'Content-Type: application/json' -d'
  15. {
  16. "settings": {
  17. "analysis": {
  18. "analyzer": {
  19. "rebuilt_standard": {
  20. "tokenizer": "standard",
  21. "filter": [
  22. "lowercase"
  23. ]
  24. }
  25. }
  26. }
  27. }
  28. }
  29. '

第9行 你可以在lowercase后面添加任意token filter

不再一一枚举内置 analyzer

Constom Analyzer

当内置的analyzer不能满足你的需求时,你可以使用合适的组合创建一个custom analyzer:

  • 0个或多个character filters
  • 1个tokenizer
  • 0个或多个token filters

    配置

    constom analyzer接受下面的参数:

  • tokenizer 内置或自定义的tokenizer(必填)

  • char_filter 内置或自定义的character filter列表(可选)
  • filete 内置或自定义的token filter列表(可选)
  • position_increment_gap 当索引文本数组时,Elasticsearch会在一个值的最后一个term和下一个值的第一个term之间插入一个假的间隙,以确保phrase query不会匹配不同数组元素的两个term。默认值100。

    配置样例

    这里有个样例,包含了下面的组合:

  • Character Filter

    • HTML Strip Character Filter
  • Tokenizer
    • Standard Tokenizer
  • Token Filters
    • Lowercase Token Filter
    • ASCII-Folding Token Filter ```shell curl -X PUT “localhost:9200/my_index?pretty” -H ‘Content-Type: application/json’ -d’ { “settings”: { “analysis”: { “analyzer”: { “my_custom_analyzer”: {
      1. "type": "custom",
      2. "tokenizer": "standard",
      3. "char_filter": [
      4. "html_strip"
      5. ],
      6. "filter": [
      7. "lowercase",
      8. "asciifolding"
      9. ]
      } } } } } ‘ curl -X POST “localhost:9200/my_index/_analyze?pretty” -H ‘Content-Type: application/json’ -d’ { “analyzer”: “my_custom_analyzer”, “text”: “Is this déjà vu?” } ‘

``` 第7行 设置type为custom是为了告诉Elasticsearch我们定义了一个custom analyzer。对比配置内置analyzer
type需要设置为内置analyzer,比如standard或者simple。

Token Filters

token filter从一个tokenizer接收一个token流,并且可以修改token(如小写),删除token(如删除停用词),或者增加token(如同义词)。
Elasticsearch有很多内置的token filter,可以用够构建custom analyzer。

Lowercase Token Filter

一个type为lowercase的token filter,可以将token文本规范化为小写。

其它内置token filter不再枚举

Character Filters

在字符流传递给tokenizer之前,character filter对其进行预处理。

不一一枚举