zoukankan      html  css  js  c++  java
  • Elasticsearch技术解析与实战-索引分词器

    1.简介

    分析是将文本,如任何电子邮件的正文转换成附加到反向索引的tokens(标记)或terms(条件)的过程。分析由分析器执行,它可以是内置的分析器,也可以是每个索引定义的自定义分析器。

    分析涉及到两个地方,索引时分析和搜索时分析。

    2.分析器

    分析器(无论是内置还是自定义)只是一个包含三个较底层组件的包:字符过滤器(Character filters),分词器(Tokenizer)、词元过滤器(Token filters)。

    内置分析器将这些组件预先封装成适用于不同语言和文本类型的分析器。Elasticsearch还暴露了各个组件,以便它们可以组合起来定义新的定制分析器。

    Character filters:

    字符过滤器接收原始文本作为字符流,并可以通过添加、删除和更改字符来转换流。例如,可以使用字符过滤器将印度-阿拉伯数字(0123456789)转换成阿拉伯-拉丁语中的(0123456789),或从流中剥离<b>等HTML元素。
    分析器可能有零个或多个字符过滤器,它们会按顺序应用。

    HTML Strip Character Filter:该 html_strip 字符串过滤器可以删除类似 <b> 的 HTML 元素和解码类似于 &amp 这样的 HTML 实体。

    参数
    escaped_tags 会在原始文本中保留的一系列标签
    案例
    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "keyword",
              "char_filter": ["my_char_filter"]
            }
          },
          "char_filter": {
            "my_char_filter": {
              "type": "html_strip",
              "escaped_tags": ["b"]
            }
          }
        }
      }
    }
    POST my_index/_analyze { "analyzer": "my_analyzer", "text": "<p>I&apos;m so <b>happy</b>!</p>" }

    返回结果
    [ 
    I'm so <b>happy</b>!
     ]

    Mapping Character Filter:该 mapping 字符串过滤器可以将所有指定的字符串替换成特定的字符串。

    参数
    mappings    一组映射,每个元素的格式为key => value。
    mappings_path    一个相对或者绝对的文件路径,指向一个每行包含一个 key =>value 映射的UTF-8编码文本映射文件。
    案例
    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "keyword",
              "char_filter": [
                "my_char_filter"
              ]
            }
          },
          "char_filter": {
            "my_char_filter": {
              "type": "mapping",
              "mappings": [
                "٠ => 0",
                "١ => 1",
                "٢ => 2",
                "٣ => 3",
                "٤ => 4",
                "٥ => 5",
                "٦ => 6",
                "٧ => 7",
                "٨ => 8",
                "٩ => 9"
              ]
            }
          }
        }
      }
    }
     
    POST my_index/_analyze
    {
      "analyzer": "my_analyzer",
      "text": "My license plate is ٢٥٠١٥"
    }
    结果
    [ My license plate is 25015 ]

    Pattern Replace Character Filter:该 pattern_replace 字符串过滤器可以将满足正则表达式的所有字符串替换成特定的字符串

    参数
    pattern    一个Java正则表达式. 必填
    replacement    替换字符串,可以使用$ 1 .. $ 9语法来引用捕获组,可以参考这里。
    flags    Java正则表达式标志。 标志应该用“|”进行分割,例如“CASE_INSENSITIVE | COMMENTS”。
    案例
    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"
    }
    结果
    [ My, credit, card, is 123_456_789 ]

    Tokenizer:

    分词器接收到一串字符,将其分解为单独的词语(通常是单个单词),并输出词语流。例如,空白分词器每当看到任何空格时,将文本分解成词语。它将文本"Quick brown fox" 转换为词语[Quick,brown,fox!]。分词器还负责记录每个词语的顺序或位置以及体现词语的原始单词开始和结束字符偏移量。
    分析器必须只有一个分词器。

    Word Oriented Tokenizers(整词分词器)
    下列的分词器通常是将整个文本分为独立的单词 : 
    
    Standard Tokenizer (标准分词器)
    standard tokenizer 根据 Unicode 文本分割算法,以单词边界分割文本。它删除大多数标点符号。 它是大多数语言的最佳选择。
    
    Letter Tokenizer
    letter tokenizer 遇到非字母时分割文本。
    
    Lowercase Tokenizer(小写分词器)
    lowercase tokenizer 类似 letter tokenizer,遇到非字母时分割文本,同时会将所有分割后的词元转为小写。
    
    Whitespace Tokenizer
    whitespace tokenizer 遇到空白字符时分割位文本。
    
    UAX URL Email Tokenizer
    uax_url_email tokenizer 类似 standard tokenizer,只不过它会把 URL 和 email 地址当成一个词元。
    
    Classic Tokenizer
    classic tokenizer 是一个基于英语语法的分词器。
    
    Thai Tokenizer(泰语分词器)
    thai tokenizer 将泰文文本分成单词。
    Partial Word Tokenizers(局部单词分词器)
    这些分词器将文本或者单词分割为小片段,用于 partial word(局部单词)的匹配 : 
    
    N-Gram Tokenizer
    ngram tokenizer 遇到指定的字符(如 : 空白、标点)时分割文本,然后返回各个单词的 n-grams(连续字符的滑动窗口)。例如  quick → [qu, ui, ic, ck]。
    
    Edge N-Gram Tokenizer
    edge_ngram tokenizer 遇到指定的字符(如 : 空白、标点)时分割文本,然后它返回锚定到单词开头的 n-gram。例如   quick → [q, qu, qui, quic, quick]。
    Structured Text Tokenizers(结构化文本分词器)
    下列的分词器通常用于结构化文本,如 身份证、邮箱、邮政编码、文件路径 : 
    
    Keyword Tokenizer
    keyword tokenizer 什么都没做,它将整个文本当成一个 词元。一般和 token 过滤器(例如  lowercase)一起使用,规范分词后的词元。
    
    Pattern Tokenizer(正则分词器)
    pattern tokenizer 使用正则表达式,在遇到单词分隔符时分割文本,或者将捕获到的匹配文本当成一个词元。
    
    Path Tokenizer(路径层次分词器)
    path_hierarchy tokenizer 把分层的值看成是文件路径,用路径分隔符分割文本,输出树上的各个节点。例如  /foo/bar/baz → [/foo, /foo/bar, /foo/bar/baz]。
    案例
    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "my_tokenizer"
            }
          },
          "tokenizer": {
            "my_tokenizer": {
              "type": "standard",
              "max_token_length": 5
            }
          }
        }
      }
    }
     
    POST my_index/_analyze
    {
      "analyzer": "my_analyzer",
      "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
    }
    结果
    [ The, 2, QUICK, Brown, Foxes, jumpe, d, over, the, lazy, dog's, bone ]

    Token filters:

    词元过滤器接收词语流,并可以添加,删除和修改词语。例如,小写词元过滤器将所有词语转换为小写,停止词元过滤器会从词语流中删除常用字(停止字),同义词词元过滤器会将同义词引入到词语流中。
    词元过滤器不允许改变每个词语的位置或字符偏移量。
    分析器可以具有零个或多个词元过滤器,它们会按顺序应用。 

    Apostrophe Token Filter(撇号/单引号过滤器)
    ASCII Folding Token Filter(ASCII Folding 词元过滤器)
    CJK Bigram Token Filter(CJK Bigram词元过滤器)
    CJK Width Token Filter(CJK宽度过滤器)
    Classic Token Filter(经典过滤器)
    Common Grams Token Filter(近义词词元过滤器)
    Compound Word Token Filter(复合词过滤器)
    Decimal Digit Token Filter(十进制数字过滤器)
    Delimited Payload Token Filter(Delimited Payload词元分析器)
    Edge NGram Token Filter(Edge NGram 词元过滤器)
    Elision Token Filter(Elision词元过滤器)
    Fingerprint Token Filter(指纹过滤器)
    Flatten Graph Token Filter(Flatten Graph 词元过滤器)
    Hunspell Token Filter(Hunspell 词元过滤器)
    Keep Types Token Filter(保留指定类型过滤器)
    Keep Words Token Filter(保留字过滤器)
    Keyword Marker Token Filter(Keyword Marker 词元过滤器)
    Keyword Repeat Token Filter(Keyword Repeat 词元过滤器)
    KStem Token Filter(KStem 词元过滤器)
    Length Token Filter(长度词元过滤器)
    Limit Token Count Token Filter(限制词元数量过滤器)
    Lowercase Token Filter(Lowercase 词元过滤器)
    Minhash Token Filter(Minhash过滤器)
    NGram Token Filter(NGram词元过滤器)
    Normalization Token Filter(标准化词元过滤器)
    Pattern Capture Token Filter(模式匹配词元过滤器)
    Pattern Replace Token Filter(模式替换词元过滤器)
    Phonetic Token Filter(Phonetic 词元过滤器)
    Porter Stem Token Filter(Porter Stem 词元过滤器)
    Reverse Token Filteredit(反向词元过滤器)
    Shingle Token Filter(Shingle 词元过滤器)
    Snowball Token Filter(Snowball 词元过滤器)
    Standard Token Filters(标准词元过滤器)
    Stemmer Override Token Filter(Stemmer Override 词元过滤器)
    Stemmer Token Filter(Stemmer 词元过滤器)
    Stop Token Filter(Stop 词元过滤器)
    Synonym Graph Token Filter(Synonym Graph 词元过滤器)
    Synonym Token Filter(Synonym 词元过滤器)
    Trim Token Filter(Trim词元过滤器)
    Truncate Token Filter(截断词元过滤器)
    Unique Token Filter(唯一词元过滤器)
    Uppercase Token Filter(Uppercase词元过滤器)
    Word Delimiter Token Filter(Word Delimiter 词元过滤器)
    案例
    "index" : {
        "analysis" : {
            "analyzer" : {
                "default" : {
                    "tokenizer" : "standard",
                    "filter" : ["standard", "my_ascii_folding"]
                }
            },
            "filter" : {
                "my_ascii_folding" : {
                    "type" : "asciifolding",
                    "preserve_original" : true
                }
            }
        }
    }

    3.测试分析器

    POST _analyze
    {
      "analyzer": "whitespace",
      "text":     "The quick brown fox."}
     
    POST _analyze
    {
      "tokenizer": "standard",
      "filter":  [ "lowercase", "asciifolding" ],
      "text":      "Is this déja vu?"}

    从analyze API的输出可以看出,分析器不仅将单词转换为词语,还记录了每个词语(用于短语查询或近义词查询)的顺序或相对位置,以及原始文本中每个词语的起始和结束字符的偏移量(用于突出搜索片段)

     4.分析器

    Elasticsearch内置有众多的分析器,可以在任何索引中使用,无需进一步配置:

    Standard Analyzer(标准分析器)

    standard(标准)分析器划分文本是通过词语来界定的,由Unicode文本分割算法定义。它删除大多数标点符号,将词语转换为小写,并支持删除停止词。

    参数:
    max_token_length    最大词语长度。如果看到超过此长度的词语,则以max_token_length分割。默认为255。
    stopwords    预定义的停止词列表,如_english或包含停止词列表的数组。默认为\_none_。
    stopwords_path    包含停止词的文件路径。
    案例
    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(简单分析器)

    simple(简单)分析器每当遇到不是字母的字符时,将文本分割为词语。它将所有词语转换为小写。

    案例
    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 ]
    Whitespace Analyzer(空白分析器)

    whitespace(空白)分析器每当遇到任何空白字符时,都将文本划分为词语。它不会将词语转换为小写。

    案例
    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. ]
    Stop Analyzer(停止分析器)

    stop(停止)分析器类似simple(简单)分析器,也支持删除停用词。

    案例
    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 ]
    Keyword Analyzer(关键字分析器)

    keyword(关键字)分析器是一个noop(空)分析器,可以接受任何给定的文本,并输出与单个词语相同的文本。

    Pattern Analyzer(模式分析器)

    pattern(模式)分析器使用正则表达式将文本拆分为词语,它支持小写和停止字。

    参数
    pattern Java正则表达式默认为 W +。 flags Java正则表达式标志。 标志应分开管道,例如“CASE_INSENSITIVE | COMMENTS”。 lowercase 是否应该降低条件? 默认为true。 stopwords 预定义的 stop 词列表,如_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 ]
    Language Analyzers(语言分析器)

    Elasticsearch提供许多特定语言的分析器,例如english(英语)或french(法语)。

    Fingerprint Analyzer(指纹分析器)

    fingerprint(指纹)分析器是专门的分析器,可以创建用于重复检测的指纹。

    案例
    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_fingerprint_analyzer": {
              "type": "fingerprint",
              "stopwords": "_english_"
            }
          }
        }
      }
    }
     
    POST my_index/_analyze
    {
      "analyzer": "my_fingerprint_analyzer",
      "text": "Yes yes, Gödel said this sentence is consistent and."
    }
    结果
    [ consistent godel said sentence yes ]
    Custom analyzers(定制分析器)

    如果你没有找到适合你需求的分析器,则可以创建一个自定义分析器,结合适当的字符过滤器,分词器和词语过滤器。

    当内置分析器不能满足您的需求时,您可以创建一个custom分析器,它使用以下相应的组合:

    参数
    tokenizer
    内置或定制的标记器。 (需要)
    
    char_filter
    内置或自定义字符过滤器的可选阵列。
    
    filter
    可选的内置或定制token过滤器阵列。
    
    position_increment_gap
    在索引文本值数组时,Elasticsearch会在一个值的最后一个值和下一个值的第一个项之间插入假的“间隙”,以确保短语查询与不同数组元素的两个术语不匹配。 默认为100.有关更多信息,请参阅position_increment_gap。
    案例
    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 ]

    5.如何配置分析器

    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "std_english": {                              #1
              "type":      "standard",
              "stopwords": "_english_"
            }
          }
        }
      },
      "mappings": {
        "my_type": {
          "properties": {
            "my_text": {
              "type":     "text",
              "analyzer": "standard",                     #2
              "fields": {
                "english": {
                  "type":     "text",
                  "analyzer": "std_english"               #3
                }
              }
            }
          }
        }
      }}
     
     
    POST my_index/_analyze
    {
      "field": "my_text",                                 #4
      "text": "The old brown cow"}
     
     
    POST my_index/_analyze
    {
      "field": "my_text.english",                         #5
       "text": "The old brown cow"}
    
    1    我们将std_english分析器定义为基于standard(标准)分析器,但是配置为删除预定义的英文停止词列表。
    24    my_text字段直接使用standard(标准)分析器,无需任何配置。这个字段没有停止词会被删除。所得的词语是:[the,old,brown,cow]
    35    my_text.english字段使用std_english分析器,因此英文停止词将被删除。得出的结论是:[old,brown.cow]

    参考资料:

    http://cwiki.apachecn.org/display/Elasticsearch/Index

  • 相关阅读:
    java如何手动创建一个线程池
    HashMap的面试总结(摘抄)
    JDK源码调试
    分布式和集群的区别
    开发中model,entity和pojo的区别
    java并发编程_CountDownLanch(倒计数锁存器)应用场景
    Map 怎么排序
    java中Thread的 interrupt异常处理
    zookeeper节点失效重连机制
    java并发库_并发库知识点整理
  • 原文地址:https://www.cnblogs.com/libin2015/p/10371369.html
Copyright © 2011-2022 走看看