Elasticsearch分析器

Elasticsearch分析器

无论是内置的分析器(analyzer),还是自定义的分析器(analyzer),都是由字符过滤器(character filters)、分词器(tokenizers) 和 token过滤器( token filters)组成。char_filter是字符过滤器,filter是token filter。

字符过滤器(character filters)
  • 字符过滤器以字符流的形式接受原始文本,并可以通过增加、删除和更改字符来转换字符流。分词之前预处理。

  • 一个analyzer可以有0个或者多个character filters。

  • HTML字符过滤器(HTML Strip Character Filter): html_strip表示提出html标签;escaped_tags表示保留html标签。

    # my_char_filter:自定义char_filter,剔除除标签外的所有的html标签
    # tokenizer:keyword  keyword分词器:整个输入作为一个单独词汇单元,方便特殊类型的文本进行索引和检索。针对邮政编码,地址等文本信息使用关键词分词器进行索引项建立非常方便
    # my_analyzer:自定义分析器
      
    DELETE my_index
    PUT my_index
    {
    "settings": {
      "analysis": {
        "char_filter": {
          "my_char_filter":{
            "type":"html_strip",
            "escaped_tags": ["a"]
          }
        }
        , "analyzer": {
          "my_analyzer":{
            "tokenizer":"keyword",
            "char_filter":"my_char_filter"
          }
        }
      }
    }
    }
    
    POST my_index/_analyze
    {
    "analyzer": "my_analyzer",
    "text": "

    I'm so happy!

    " } { "tokens" : [ { // 过滤之后的结果 "token" : """ I'm so happy! """, "start_offset" : 0, "end_offset" : 32, "type" : "word", "position" : 0 } ] }
  • 映射字符过滤器(Mapping Character Filter): type -> mapping 字符映射

    # my_char_filter:自定义char_filter,利用type=mapping进行字符替换
    # tokenizer:keyword  keyword分词器:整个输入作为一个单独词汇单元,方便特殊类型的文本进行索引和检索。针对邮政编码,地址等文本信息使用关键词分词器进行索引项建立非常方便
    # my_analyzer:自定义分析器
      
    DELETE my_index
    PUT my_index
    {
    "char_filter": {
        "my_char_filter": {
            "type": "mapping",
            "mappings": [
                "٠ => 0",
                "١ => 1",
                "٢ => 2",
                "٣ => 3",
                "٤ => 4",
                "٥ => 5",
                "٦ => 6",
                "٧ => 7",
                "٨ => 8",
                "٩ => 9"
            ]
        }
    },
    "settings": {
        "analysis": {
            "analyzer": {
                "my_analyzer": {
                    "tokenizer": "keyword",
                    "char_filter": [
                        "my_char_filter"
                    ]
                }
            }
    
        }
    }
    }
    POST my_index/_analyze
    {
    "analyzer": "my_analyzer",
    "text": "My license plate is ٢٥٠١٥"
    }
    
    {
    "tokens" : [
      {
        "token" : "My license plate is 25015",
        "start_offset" : 0,
        "end_offset" : 25,
        "type" : "word",
        "position" : 0
      }
    ]
    }
    
  • 模式替换过滤器(Patten Replace Character Filter): type -> patten_replace 正则匹配

    DELETE my_index
    # my_analyzer:自定义模式匹配分析器,正则匹配上的字符串将不再分词
    PUT my_index
    {
    "settings": {
      "analysis": {
        "analyzer": {
          "my_analyzer": {
            "tokenizer": "standard",
            "char_filter": ["my_char_filter"]
          }
        },
        "char_filter": {
          "my_char_filter": {
            "type": "pattern_replace",
            "pattern": "(\\d+)-(?=\\d)",
            "replacement": "$1_"
          }
        }
      }
    }
    }
    
    POST my_index/_analyze
    {
    "analyzer": "my_analyzer",
    "text": "My credit card is 123-456-789"
    }
    
    {
    "tokens" : [
      {
        "token" : "My",
        "start_offset" : 0,
        "end_offset" : 2,
        "type" : "",
        "position" : 0
      },
      {
        "token" : "credit",
        "start_offset" : 3,
        "end_offset" : 9,
        "type" : "",
        "position" : 1
      },
      {
        "token" : "card",
        "start_offset" : 10,
        "end_offset" : 14,
        "type" : "",
        "position" : 2
      },
      {
        "token" : "is",
        "start_offset" : 15,
        "end_offset" : 17,
        "type" : "",
        "position" : 3
      },
      {
        "token" : "123_456_789",
        "start_offset" : 18,
        "end_offset" : 29,
        "type" : "",
        "position" : 4
      }
    ]
    }
    
分词器(Tokenizer)
  • 一个分词器接受一个字符流,并将其拆分成单个token(通常是单个单词),并输出一个token流。

  • Tokenizer负责将文本拆分成单个token(一个一个的单词,这些单词叫token),就是一段文本被分隔成好几部分,相当于java的split。

  • 分词器负责记录每个term的书序或位置,以及term所表示的原单词的开始和结束字符偏移量(文本被分词后的输出是一个term数组)。

  • 一个分析器必须只能一个分词器

  • ES内置分词器 7.6 15种 自带分词器
    ① standard analyzer:默认分词器,中文支持的不理想,会逐字拆分。
    1) max_token_length:最大令牌长度。如果看到令牌超过此长度,则将其max_token_length间隔分割。默认为255。
    ② Pattern Tokenizer:以正则匹配分隔符,把文本拆分成若干词项。
    ③ Simple Pattern Tokenizer:以正则匹配词项,速度比Pattern Tokenizer快。
    ④ whitespace analyzer:以空白符分隔 Tim_cookie

  • 代码样例:

    #设置type为custom告诉Elasticsearch我们正在定义一个定制分析器。将此与配置内置分析器的方式进行比较: type将设置为内置分析器的名称,如 standard或simple
    
    # 自定义字符过滤器 test_char_filter ,将 & 替换为 and | 替换为 or
    # 自定义token filter, 停用词 is、in、at、the、a、for
    # 分词器增加标点过滤:模式匹配,去除 .,!? 四种标点符号    
    # 自定义分析器 my_analyzer 汇总以上三种自定义,同时character filter增加提出html,token  filter 增加 字母小写。    
    PUT /test_analysis
    {
    "settings": {
      "analysis": {
        "char_filter": {
          "test_char_filter": {
            "type": "mapping",
            "mappings": [
              "& => and",
              "| => or"
            ]
          }
        },
        "filter": {
          "test_stopwords": {
            "type": "stop",
            "stopwords": ["is","in","at","the","a","for"]
          }
        },
        "tokenizer": {
          "punctuation": { 
            "type": "pattern",
            "pattern": "[ .,!?]"
          }
        },
        "analyzer": {
          "my_analyzer": {
            "type": "custom",
            "char_filter": [
              "html_strip",
              "test_char_filter"
            ],
            "tokenizer": "standard",
            "filter": ["lowercase","test_stopwords"]
          }
        }
      }
    }
    }
    
    GET /test_analysis/_analyze
    {
    "text": "Teacher ma & zhang also thinks [mother's friends] is good | nice!!!",
    "analyzer": "my_analyzer"
    }
    
    # 执行结果
    {
    "tokens" : [
      {
        "token" : "teacher",
        "start_offset" : 0,
        "end_offset" : 7,
        "type" : "",
        "position" : 0
      },
      {
        "token" : "ma",
        "start_offset" : 8,
        "end_offset" : 10,
        "type" : "",
        "position" : 1
      },
      {
        "token" : "and",
        "start_offset" : 11,
        "end_offset" : 12,
        "type" : "",
        "position" : 2
      },
      {
        "token" : "zhang",
        "start_offset" : 13,
        "end_offset" : 18,
        "type" : "",
        "position" : 3
      },
      {
        "token" : "also",
        "start_offset" : 19,
        "end_offset" : 23,
        "type" : "",
        "position" : 4
      },
      {
        "token" : "thinks",
        "start_offset" : 24,
        "end_offset" : 30,
        "type" : "",
        "position" : 5
      },
      {
        "token" : "mother's",
        "start_offset" : 32,
        "end_offset" : 40,
        "type" : "",
        "position" : 6
      },
      {
        "token" : "friends",
        "start_offset" : 41,
        "end_offset" : 48,
        "type" : "",
        "position" : 7
      },
      {
        "token" : "good",
        "start_offset" : 53,
        "end_offset" : 57,
        "type" : "",
        "position" : 9
      },
      {
        "token" : "or",
        "start_offset" : 58,
        "end_offset" : 59,
        "type" : "",
        "position" : 10
      },
      {
        "token" : "nice",
        "start_offset" : 60,
        "end_offset" : 64,
        "type" : "",
        "position" : 11
      }
    ]
    }    
    
Token过滤器(token filters)
  • token filters接受token流,并且可能会增加、删除或者更改token流;

  • 不允许token过滤器更改每个token的位置和字符偏移。

  • 一个分词器可能有0个或者多个token过滤器,它们按照顺序应用。

  • 一般负责时态转换、大小写转换、同义词转换、语气词处理等。比如 has=>have him=>he apples=>apple the/oh/a=>干掉

  • 代码样例-1:

    DELETE my_index
    # setting 设置索引配置
    # my_token_filter:自定义token过滤器,1~20个字符词条才会被搜索  
    # my_analyzer:自定义分析器;使用的token过滤器有:lowercase(系统)  和 my_token_filter(自定义) 
    # type:custom 固定写法,表示自定义分析器
    # tokenizer:standard 系统自带的分词器。
    # mappings中定义字段映射,使用自定义的分析器。
    # analyzer 指的是在建索引时的分词策略
    # search_analyzer 指的是在查询时的分词策略    
      
    PUT my_index
    {
    "settings": {
      "analysis": {
        "filter": {
          "my_token_filter":{
            "type":"edge_ngram",
            "min_gram":1,
            "max_gram":20
          }
        }
        , "analyzer": {
          "my_analyzer":{
            "type":"custom",
            "tokenizer":"standard",
            "filter":[
              "lowercase",
              "my_token_filter"
            ]
          }
        }
      }
    }
    , "mappings": {
      "properties": {
        "keyword":{
          "type": "text"
          , "analyzer": "my_analyzer"
          , "search_analyzer": "standard"
        }
      }
    }
    }
    
  • 代码样例-2:

    # 利用stardard 将文本分词之后的所有token进行小写。
    GET _analyze
    {
    "tokenizer" : "standard",
    "filter" : ["lowercase"],
    "text" : "THE Quick FoX JUMPs"
    }
    
    # 自定义条件token过滤器
    GET /_analyze
    {
    "tokenizer":"standard",
    "filter": [
      {
        "type": "condition",
        "filter": [
          "lowercase"
        ],
        "script": {
          "source": "token.getTerm().length() < 5"
        }
      }
    ],
    "text": "THE QUICK BROWN FOX"
    }
    
  • 代码样例-3:

    # 自定义分析器,采用英语内置的stopword(停用词)
    PUT /my_index
    {
    "settings": {
      "analysis": {
        "analyzer": {
          "my_analyzer":{
            "type":"standard",
            "stopwords":"_english_"
          }
        }
      }
    }
    }
    GET my_index/_analyze
    {
    "analyzer": "my_analyzer",
    "text": "Teacher Ma is in the restroom"
    }
    

停用词:

  • 停用词过滤:是文本分析中一个预处理方法。它的功能是过滤分词结果中的噪声(例如:的、是、啊等)

  • 停用词:指在信息检索中,为节省存储空间和提高搜索效率,在处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词)。这些停用词都是人工输入、非自动化生成的,生成后的停用词会形成一个停用词表。但是,并没有一个明确的停用词表能够适用于所有的工具。甚至有一些工具是明确地避免使用停用词来支持短语搜索的。

  • 移除停用词的工作是由stop停用词过滤器完成的,可以通过创建自定义分析器来使用它。但是也有一些自带的分析器预制使用停用词过滤器

  • 语言分析器:每个语言分析器默认使用 该语言相适应的停用词列表。特定语言的默认停用词,可以通过使用 _lang_ 符号来指定。如 english 英语分析器使用 :_english_ 停用词列表。"stopwords": "_english_";

    # 默认的停用词是 _english_
    # 本例通过 _none_ 禁用了停用词    
    PUT /my_index
    {
    "settings": {
      "analysis": {
        "analyzer": {
          "my_english": {
            "type":      "english", 
            "stopwords": "_none_" 
          }
        }
      }
    }
    }
    # 停用词 可以指定路径
    # 停用词文件的路径,该路径相对于 Elasticsearch 的 config 目录    
    PUT /my_index
    {
    "settings": {
      "analysis": {
        "analyzer": {
          "my_english": {
            "type":           "english",
            "stopwords_path": "stopwords/english.txt" 
          }
        }
      }
    }
    }
    
  • standard 标准分析器:默认使用空的停用词列表:_none_,实际是禁用了停用词。

    # 自定义分析器 my_analyzer
    # 标准的standard分析器,进行了一些自定义配置
    # 过滤掉停用词 and 和 the    
    PUT /my_index
    {
    "settings": {
      "analysis": {
        "analyzer": {
          "my_analyzer": { 
            "type": "standard", 
            "stopwords": [ "and", "the" ] 
          }
        }
      }
    }
    }
    
  • pattern模式分析器:与standard分析器类似,默认使用空的的停用词里诶博爱:为_none_。

分词器(analyzer)处理过程

分词器处理过程.jpg

搜索引擎的人性化(Normalization)

为key_words提供更加完整的倒排索引。

如:时态转化(like | liked),单复数转化(man | men),全写简写(china | cn),同义词(small | little)等。

如:china 搜索时,如果条件为cn是否可搜索到。

如:dogs,搜索时,条件为dog是否可搜索到数据。

如果可以使用简写(cn)或者单复数(dog&dogs)搜索到想要的结果,那么称为搜索引擎normalization人性化。

normalization是为了提升召回率的(recall),就是提升搜索能力的。

normalization是配合分词器(analyzer)完成其功能的。

分词器的功能就是处理Document中的field的。就是创建倒排索引过程中用于切分field数据的。

如:I think dogs is human’s best friend.在创建倒排索引的时候,使用分词器实现数据的切分。

上述的语句切分成若干的词条,分别是: think dog human best friend。

常见搜索条件有:think、 human、 best、 friend,很少使用is、a、the、i这些数据作为搜索条件。

你可能感兴趣的:(Elasticsearch分析器)