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,剔除除<a>标签外的所有的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": "<p>I&apos;m so <a>happy</a>!</p>"
    }
    
    {
    "tokens" : [
      {
        // 过滤之后的结果  
        "token" : """
    I'm so <a>happy</a>!
    """,
        "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" : "<ALPHANUM>",
        "position" : 0
      },
      {
        "token" : "credit",
        "start_offset" : 3,
        "end_offset" : 9,
        "type" : "<ALPHANUM>",
        "position" : 1
      },
      {
        "token" : "card",
        "start_offset" : 10,
        "end_offset" : 14,
        "type" : "<ALPHANUM>",
        "position" : 2
      },
      {
        "token" : "is",
        "start_offset" : 15,
        "end_offset" : 17,
        "type" : "<ALPHANUM>",
        "position" : 3
      },
      {
        "token" : "123_456_789",
        "start_offset" : 18,
        "end_offset" : 29,
        "type" : "<NUM>",
        "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" : "<ALPHANUM>",
        "position" : 0
      },
      {
        "token" : "ma",
        "start_offset" : 8,
        "end_offset" : 10,
        "type" : "<ALPHANUM>",
        "position" : 1
      },
      {
        "token" : "and",
        "start_offset" : 11,
        "end_offset" : 12,
        "type" : "<ALPHANUM>",
        "position" : 2
      },
      {
        "token" : "zhang",
        "start_offset" : 13,
        "end_offset" : 18,
        "type" : "<ALPHANUM>",
        "position" : 3
      },
      {
        "token" : "also",
        "start_offset" : 19,
        "end_offset" : 23,
        "type" : "<ALPHANUM>",
        "position" : 4
      },
      {
        "token" : "thinks",
        "start_offset" : 24,
        "end_offset" : 30,
        "type" : "<ALPHANUM>",
        "position" : 5
      },
      {
        "token" : "mother's",
        "start_offset" : 32,
        "end_offset" : 40,
        "type" : "<ALPHANUM>",
        "position" : 6
      },
      {
        "token" : "friends",
        "start_offset" : 41,
        "end_offset" : 48,
        "type" : "<ALPHANUM>",
        "position" : 7
      },
      {
        "token" : "good",
        "start_offset" : 53,
        "end_offset" : 57,
        "type" : "<ALPHANUM>",
        "position" : 9
      },
      {
        "token" : "or",
        "start_offset" : 58,
        "end_offset" : 59,
        "type" : "<ALPHANUM>",
        "position" : 10
      },
      {
        "token" : "nice",
        "start_offset" : 60,
        "end_offset" : 64,
        "type" : "<ALPHANUM>",
        "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这些数据作为搜索条件。

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