zoukankan      html  css  js  c++  java
  • Elasticsearch从入门到放弃:分词器初印象

    Elasticsearch 系列回来了,先给因为这个系列关注我的同学说声抱歉,拖了这么久才回来,这个系列虽然叫「Elasticsearch 从入门到放弃」,但只有三篇就放弃还是有点过分的,所以还是回来继续更新。

    之前我们聊过了 Elasticsearch 的索引文档,不太熟悉的话可以先翻阅一下前文。今天再一起聊一下 Elasticsearch 的分词器。

    关于分词

    如果你是讲 Elasticsearch 作为搜索引擎,那么你应该需要对分词进行了解,Elasticsearch 的分词是将全文本转换为一系列单词,这样有助于在搜索时得到相关的结果以及相关性分析。例如我们有一个文本为“I love Elasticsearch”,然后 Elasticsearch 可以将其分解为三个单词,这时我们无论搜索哪个单词,都能搜到这个文本。

    Elasticsearch 通过分词器对文本进行分词处理,Elasticsearch 的分词器是由 Character Filters、Tokenizer 和Token Filter 三部分组成。在介绍它们之前,我们先来简单了解一下 Analyze API,它可以帮助我们快速测试一个 Analyzer 的作用,它的用法也非常简单:

    GET /_analyze
    {
      "analyzer" : "standard",
      "text" : "Quick Brown Foxes!"
    }
    

    其中,analyzer 是指定的分词器,text 是被测试的文本,这样就能得到这个文本分词后的效果。

    这是最简单的一种用法,此外,我们还可以在 path 中指定 index,用于测试指定索引中 mapping 设置的 analyzer 或者索引默认的 analyzer。当然,你也可以测试一下自定义的 analyzer,只需要在参数中设置好 Character Filters、Tokenizer 和Token Filter 即可。关于 Analyze API 更多的使用方法可以自行查阅官方文档 Analyze API

    内置 Analyzer

    为了方便使用,Elasticsearch 为我们提供了几种内置 Analyzer:

    • Fingerprint:它可以将文本处理为小写的、去除扩展的、有序的、唯一的单词
    • Keyword:不分词
    • Language:提供了30多种常见语言的分词器
    • Pattern:使用正则表达式分词,默认W+(非字符分隔)
    • Simple:按照非字母切分,小写处理
    • Standard:默认分词器,会基于 Unicode 文本语法,按照单词划分,并进行小写处理
    • Stop:小写处理,过滤停用词(the, a, is)
    • Whitespace:按照空格切分,不转小写

    现在我们来测试一下 Whitespace Analyzer

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

    它的执行结果是

    {
      "tokens" : [
        {
          "token" : "The",
          "start_offset" : 0,
          "end_offset" : 3,
          "type" : "word",
          "position" : 0
        },
        {
          "token" : "2",
          "start_offset" : 4,
          "end_offset" : 5,
          "type" : "word",
          "position" : 1
        },
        {
          "token" : "QUICK",
          "start_offset" : 6,
          "end_offset" : 11,
          "type" : "word",
          "position" : 2
        },
        {
          "token" : "Brown-Foxes",
          "start_offset" : 12,
          "end_offset" : 23,
          "type" : "word",
          "position" : 3
        },
        {
          "token" : "jumped",
          "start_offset" : 24,
          "end_offset" : 30,
          "type" : "word",
          "position" : 4
        },
        {
          "token" : "over",
          "start_offset" : 31,
          "end_offset" : 35,
          "type" : "word",
          "position" : 5
        },
        {
          "token" : "the",
          "start_offset" : 36,
          "end_offset" : 39,
          "type" : "word",
          "position" : 6
        },
        {
          "token" : "lazy",
          "start_offset" : 40,
          "end_offset" : 44,
          "type" : "word",
          "position" : 7
        },
        {
          "token" : "dog's",
          "start_offset" : 45,
          "end_offset" : 50,
          "type" : "word",
          "position" : 8
        },
        {
          "token" : "bone.",
          "start_offset" : 51,
          "end_offset" : 56,
          "type" : "word",
          "position" : 9
        }
      ]
    }
    

    如果有兴趣,可以自行测试一下其他的内置 Analyzer。除了内置的 Analyzer 之外,你也可以根据需要自定义分词器。

    下面我们来看怎么定义我们需要的 Analyzer。

    前面提到 Analyzer 由三部分组成,其中 Character Filters 用于对原始文本进行处理(例如去掉html标签),Tokenizer 是按照指定规则进行切分,Token Filter 负责将切分的单词进行加工(例如转小写)。

    Character Filters

    Character Filters 是分词的第一步,Elasticsearch 用它来对原始文本进行一些处理。内置的 Character Filters 有三个,分别是:

    • HTML strip:使用解码值替换HTML标签
    • Mapping:使用指定的替换项替换指定的字符串
    • Pattern replace:使用指定的替换项替换正则匹配的字符串

    HTML strip 默认会替换文本中所有的 HTML 标签,你也可以通过设置escaped_tags,将一些特定的标签排除

    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "keyword",
              "char_filter": [
                "my_custom_html_strip_char_filter"
              ]
            }
          },
          "char_filter": {
            "my_custom_html_strip_char_filter": {
              "type": "html_strip",
              "escaped_tags": [
                "b"
              ]
            }
          }
        }
      }
    }
    

    这个自定义 Analyzer 就不会替换标签 b。

    Tokenizer

    在对原始文本进行初步的处理之后,Tokenizer 就要上场了,它帮助我们根据指定的规则进行分词,Elasticsearch 同样提供了一些内置的 Tokenizer。

    • Character group:按照配置的字符组进行切分
    • Classic:针对英语语法进行分词
    • Edge n-gram:从单词的起始字符开始按长度依次切分quick 会被分为[q, qu, qui, quic, quick]
    • Keyword:不切分
    • Letter:遇到非字母的字符进行切分
    • Lowercase:与类似 Letter 类似,不过它会把切分后的单词转为小写
    • N-gram:把单词切分为指定长度的字符串集合,quick 会被分为[qu, ui, ic, ck]
    • Path hierarchy:对路径进行切分,/foo/bar/baz 会分为[/foo, /foo/bar, /foo/bar/baz]
    • Pattern:根据正则匹配进行切分
    • Simple pattern:正则会受到一些限制,但不支持按照匹配到的分割符切分
    • Simple pattern split:是支持按照匹配到的分割符切分的Simple pattern
    • Standard:按照单词进行切分
    • Thai:针对泰语进行切分
    • UAX URL email:与 Standard 相似,但它会把 url 或邮箱当作一个整体
    • Whitespace:按照空格进行切分

    在这里你可以先对这些内置的 Tokenizer 有个初步的了解,知道它们能干什么,在具体使用的时候可以查阅官方文档进行更详细的了解,很多 Tokenizer 还支持一些参数配置,这些到实际场景中灵活使用就好。

    Token Filter

    Elasticsearch 内置的 Token Filter 非常多,这里列几个常用的吧:

    • Trim:删除前后空格
    • Uppercase:转大写
    • Lowercase:转小写
    • Stop:停用词过滤
    • ……

    Elasticsearch 中内置的这些分词器及组件可以满足我们日常的大部分需求了,能够做到灵活应用就很厉害了。如果真的遇到解决不了的问题,你也可以尝试自定义分词器,例如对我们的中文进行分词。

    中文分词

    中文分词的难点在于,它不像英文那样有天然的空格可以进行切分,我们也不能简单的把它分成一个个的字,而是要分成有意义的词。

    比较不错的中文分词器有 ICU Analyzer、IK 和 THULAC

    ICU Analyzer

    ICU Analyzer 并不是 Elasticsearch 内置的分词器,所以我们需要预先安装插件才能使用

    执行命令

    elasticsearch-plugin install analysis-icu
    

    进行安装,安装好以后可以使用命令elasticsearch-plugin list进行查看。

    安装好之后就可以运行下面这个例子

    GET _analyze
    {
      "analyzer": "standard", 
      "text": "觉得好看就点赞"
    }
    
    GET _analyze
    {
      "analyzer": "icu_analyzer", 
      "text": "觉得好看就点赞"
    }
    

    你会发现 standard analyzer 就是把这句话拆成一个个字,而 icu analyzer 基本会根据语义进行拆分。

    总结

    经过本文的介绍,相信你对 Elasticsearch 的分词器也有了一个初步的认识,知道它由什么组成,能够使用 Analyze API 对一个分词器进行简单的测试,也基本能够自定义一些分词器了。

    我对内置的 Token Filter 介绍的比较少,你可以结合官方文档,对你感兴趣的 Token Filter 进行更深入的研究,如果有什么问题也欢迎和我讨论。

  • 相关阅读:
    UPS FAQ-不错的UPS资料
    HPL.dat FAQ
    Fortran77计算某段代码的CPU运行时间
    存储知识 什么是LUN?LUN有什么用?对理解存储设备很有好处
    HPL.dat Tune
    UPS-瓦特(W)和伏安(VA):易混淆的两个概念
    mysql sql 索引相关用法,加快查询速度
    mysql 数据库分类设计方法与PHP结合
    c# SQLServer 数据库连接类
    .net上传图片生成大小缩略图
  • 原文地址:https://www.cnblogs.com/Jackeyzhe/p/13210900.html
Copyright © 2011-2022 走看看