ES分词器介绍

什么是分词器

分词属于ES的文本分析功能,是将文本(如任何的电子邮件的正文),转换成 tokens / terms的过程,再将这些 tokensterms 添加到倒排索引中以进行搜索服务。 分词器就是用来执行上述工作的。这里的分词器指的是 analyzer,ES提供了内置的分词器,也可以进行自定义分词器。

分词器的组成

一个标准的分词器包含三个部分,character filterstokenizerstoken filters

Character filters

字符过滤器将原始文本作为字符流接收,并可以通过添加、删除或更改字符来转换流。 例如,字符过滤器可用于将印度-阿拉伯数字 (٠ ١٢٣٤٥٦٧٨ ٩ ) 转换为阿拉伯-拉丁语等价物 (0123456789),或从流中去除诸如“”之类的 HTML 元素。

分词器可能有零个或多个 字符过滤器,它们按顺序应用。

Tokenizers

tokenizer分词器 接收字符流,将其分解为单独的 tokens(通常是单个单词),并输出 tokens 流。 例如,whitespace 分词器在看到任何空格时将文本分解为tokens。 它会将文本“Quick brown fox!”转换为terms[Quick, brown, fox!]

tokenizer分词器还负责记录每个词条的顺序或位置,以及该词条所代表的原始单词的开始和结束字符偏移量

分词器必须具有正好一个 tokenizer

Token filters

token 过滤器 接收token流并可以添加、删除或更改token 。 例如,一个 lowercase 标记过滤器将所有标记转换为小写,一个 stop 标识过滤器从标识流中删除常用词(停用词),如 the ,并且 synonym token过滤器将同义词引入token流。

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

分词器可能有零个或多个 token filters,它们按顺序应用。

分词的过程

在这里插入图片描述

写入时分词

在写入时,内置的 english analyzer 将首先句子转换成做个单词标记。然后将这些单词标记转换成小写,然后删除过滤词,并将单词转换成词干(foxes → fox,jumped → jump,lazy → lazi),最后将term存储在倒排索引中。

mapping中的每个 text 类型字段都可以指定自己的 analyzer

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type":     "text",
          "analyzer": "standard"
        }
      }
    }
  }
}

在写入索引时,如果没有指定 analyzer,它会在索引设置中查找名为 default 的分析器。 否则,它默认使用 standard 分析器

搜索时分词

full text query 中,在搜索时将相同的分析过程应用于查询的字符串,例如 match query 将查询字符串中的文本转换的terms形式为存储在倒排索引中的存储的terms相同。

例如,用户可能会搜索:

"a quick fox"

这将由相同的english分析器分析为以下terms:

[ quick, fox ]

即使查询字符串中使用的确切单词没有出现在原始文本中(quick vs QUICKfox vs foxes),因为我们对文本和查询字符串中应用了相同的分析器 ,查询字符串中的terms与倒排索引中文本中的terms完全匹配,这意味着该查询将匹配我们的示例文档。

通常应在索引时和搜索时使用相同的分析器。以及 全文查询match 查询 将使用映射来查找每个字段使用的分析器。

用来搜索特定字段的分析器通过查找以下内容来确定:

  • 在查询体本身中指定的analyzer
  • search_analyzer 映射参数。
  • analyzer 映射参数。
  • 索引设置中称为default_search的分析器。
  • 索引设置中称为default的分析器。
  • standard分析器。

测试分词效果

ES提供了一个analyze API ,用来查询分词的结果。

Positions and character offsets

As can be seen from the output of the analyze API, analyzers not only convert words into terms, they also record the order or relative positions of each term (used for phrase queries or word proximity queries), and the start and end character offsets of each term in the original text (used for highlighting search snippets).
位置和字符偏移

从analyze API的输出可以看出,analyzer不仅将语句转化为词,还记录了每个词的顺序或相对位置(用于词组查询或词邻近查询),以及词的开始和结束字符偏移量。 原始文本中的每个更专业的词汇(用于突出显示搜索片段)。

在请求体重内联式的指定分词器:

POST _analyze
{
  "analyzer": "whitespace",
  "text":     "The quick brown fox."
}	

也可以在请求中内联指定内置标记器、标记过滤器和字符过滤器的组合:

POST _analyze
{
  "tokenizer": "standard",
  "filter":  [ "lowercase", "asciifolding" ],
  "text":      "Is this déja vu?"
}

同样的也可以在自定义类型的分词器中运行analyze API :

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_folded": {              // 自定义一个叫std_folded的分析器
          "type": "custom",
          "tokenizer": "standard",   // 标准标记器
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "my_text": {
          "type": "text",
          "analyzer": "std_folded"  // 在my_text字段上使用了这个分析器
        }
      }
    }
  }
}



GET my_index/_analyze             // 通过api直接指明分词器的方式分词效果
{
  "analyzer": "std_folded", 
  "text":     "Is this déjà vu?"
}


GET my_index/_analyze            // 通过api查询字段使用的分词器查询分词效果
{
  "field": "my_text", 
  "text":  "Is this déjà vu?"
}

分词器的分类

ES内置的分词器有(以6.7版本为基准):

中文分词器:

使用示例

以Standard Analyzer为例

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

内置的标准分析器包含以下部分:

  • 分词器:英文分词可以根据空格将单词分开,中文分词比较复杂,可以采用机器学习算法来分词。

  • Token过滤器:对切分的单词进行加工。

测试分析效果
POST _analyze
{
  "analyzer": "standard",
  "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 ]

在本例中,我们将 standard 分析器配置为 max_token_length 为 5(出于演示目的),并使用预定义的英语停用词列表:

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_english_analyzer": {
          "type": "standard",     // 分词器类型
          "max_token_length": 5,  // 可以分词的词汇的最大长度为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 ]

如果需要配置参数之外的标准型分词器,那么您需要将其重新创建为 custom 分词器并对其进行修改,通常是通过添加token过滤器。 这将重新创建内置的standard分析器:

PUT /standard_example
{
  "settings": {
    "analysis": {
      "analyzer": {
        "rebuilt_standard": {       // 自定义定义分词器名称
          "tokenizer": "standard",
          "filter": [
            "lowercase"       
          ]
        }
      }
    }
  }
}

其他:Normalizers(规范器)

规范器与分析器类似,只是它们只能发出一个标记。 因此,它们没有标记器,只接受可用字符过滤器标记过滤器的子集。 只允许使用基于每个字符的过滤器。 例如,允许使用小写过滤器,但不允许使用词干过滤器,它需要将关键字视为一个整体。 当前可以在规范化器中使用的过滤器列表如下:arabic_normalizationasciifoldingbengali_normalizationcjk_widthdecimal_digitelisiongerman_normalizationhindi_normalizationindic_normalization , 小写, persian_normalization, scandinavian_folding, serbian_normalization, sorani_normalization, uppercase

到目前为止,Elasticsearch 还没有内置规范化器,因此获得规范化器的唯一方法是构建自定义规范化器。 自定义规范化器采用 字符过滤器token filters

PUT index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "quote": {
          "type": "mapping",
          "mappings": [
            "« => \"",
            "» => \""
          ]
        }
      },
      "normalizer": {
        "my_normalizer": {
          "type": "custom",
          "char_filter": ["quote"],
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "foo": {
          "type": "keyword",
          "normalizer": "my_normalizer"
        }
      }
    }
  }
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐