Elasticsearch 分析(Analysis)

迷南。 2021-12-01 14:40 487阅读 0赞

什么是 Analysis(分析)

Analysis 是指对全文本(Full Text)进行分词,以便生成供搜索用的倒排索引

这个过程是由 analyzer(分析器) 来完成的。

分析器(Analyzer)

分析器主要包含三个组成部分。

  • 字符过滤器
  • 分词器
  • 标记过滤

字符过滤器(Character Filter) : 文本字符串首先会经过字符过滤器的预处理,过滤掉无用的字符(如 HTML 标记),将 “&” 转换为 “and” 等。

分词器(Tokenizer) : 能够将字符串拆分为一个个独立的 token 或 term。

过滤器(Filter) : 经过分词器处理后的一系列 token ,可以由过滤器再次进行处理。比如,修改 token(转换为小写)、删除无用的 token(如 the)、增加同义词等等。

分词器(Tokenizer)

Tokenizer 是 Analyzer 最重要的组成部分。

Elasticsearch 中有很多内置的 Tokenizer,我们可以用它来创建自定义的 Analyzer。

这些内置的 Tokenizer,可以分为三大类:

  • 单词分词器
  • 局部单词分词器
  • 结构化文本分词器

单词分词器

单词分词器(Word Tokenizer)主要用于将全文本拆分为独立的单词。

单词分词器主要包含以下几种:

  • Standard Tokenizer(标准分词器):基于单词边界将文本拆分为独立的项,它会删除大多数标点符号。
  • Letter Tokenizer(字母分词器):拆分文本时,如果遇到非字母就进行拆分。
  • Lowercase Tokenizer(小写字母分词器):和字母分词器类似,它还会将拆分后的项转化为小写字母。
  • Whitespace Tokenizer(空格分词器):顾名思义,拆分文本时,如果遇到任何空格就进行拆分。
  • UAX URL Email Tokenizer(URL & Email分词器):和标准分词器类似,它还可以对 URL 和 Email 进行拆分。
  • Classic Tokenizer(经典分词器):根据英文语法来拆分文本。
  • Thai Tokenizer(泰文分词器):根据泰文语法来拆分文本。

局部单词分词器

局部单词分词器(Partial Word Tokenizer)可用于根据将文本或单词拆分为更小的片段。

它主要包含一些几种:

  • N-Gram Tokenizer:基于指定的特殊字符(如空格、标点符号),将文本拆分为独立的词,并返回词的局部片段。如:quick → [qu, ui, ic, ck]。
  • Edge N-Gram Tokenizer:基于指定的特殊字符(如空格、标点符号),将文本拆分为独立的词,并返回词的局部片段。如:quick → [q, qu, qui, quic, quick]。

结构化文本分词器

结构化文本分词器(Structured Text Tokenizer)可用于处理结构化的特殊文本,如身份证号、电子邮箱、邮编、路径等。

  • Keyword Tokenizer(关键字分词器):它可以处理任何文本,并将其作为确切的独立项返回。关键字分词器可以结合过滤器一起使用,将独立的项标准化为小写。
  • Pattern Tokenizer(正则分词器):它可以基于正则表达式的匹配项来拆分特殊文本。
  • Path Tokenizer(路径分词器):根据路径的层次结构对路径进行分词。如:文件系统的路径,/foo/bar/baz → [/foo, /foo/bar, /foo/bar/baz ]。

自定义分析器

如果 Elasticsearch 内置的 Analyzer 无法满足你的需求,你就可以自定义分析器(Custom Analyzer)。

自定义分析器通常包含:

  • 0 个或多个字符过滤器(Character Filter)
  • 1 个分词器(Tokenizer)
  • 0 个或多个过滤器(Filter)

如下,是一个给索引库设置自定义分析器的示例:

  1. PUT /my_index
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "my_custom_analyzer": {
  7. "type": "custom",
  8. "tokenizer": "standard",
  9. "char_filter": [
  10. "html_strip"
  11. ],
  12. "filter": [
  13. "lowercase",
  14. "asciifolding"
  15. ]
  16. }
  17. }
  18. }
  19. }
  20. }

返回结果:

  1. {
  2. "acknowledged": true,
  3. "shards_acknowledged": true
  4. }

我们来测试上面的自定义分析器。

  1. POST /my_index/_analyze
  2. {
  3. "analyzer": "my_custom_analyzer",
  4. "text": "<b>Is this your dog</b>?"
  5. }

返回结果:

  1. {
  2. "tokens": [
  3. {
  4. "token": "is",
  5. "start_offset": 3,
  6. "end_offset": 5,
  7. "type": "<ALPHANUM>",
  8. "position": 0
  9. },
  10. {
  11. "token": "this",
  12. "start_offset": 6,
  13. "end_offset": 10,
  14. "type": "<ALPHANUM>",
  15. "position": 1
  16. },
  17. {
  18. "token": "your",
  19. "start_offset": 11,
  20. "end_offset": 15,
  21. "type": "<ALPHANUM>",
  22. "position": 2
  23. },
  24. {
  25. "token": "dog",
  26. "start_offset": 16,
  27. "end_offset": 23,
  28. "type": "<ALPHANUM>",
  29. "position": 3
  30. }
  31. ]
  32. }

上面自定义的那个分析器,用到的 char_filter、tokenizer 和 filter 其实都是它们的默认配置。这里,我们来自定义一个复杂的分析器。

  1. PUT my_index
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "my_custom_analyzer": {
  7. "type": "custom",
  8. "char_filter": [
  9. "emoticons"
  10. ],
  11. "tokenizer": "punctuation",
  12. "filter": [
  13. "lowercase",
  14. "english_stop"
  15. ]
  16. }
  17. },
  18. "tokenizer": {
  19. "punctuation": {
  20. "type": "pattern",
  21. "pattern": "[ .,!?]"
  22. }
  23. },
  24. "char_filter": {
  25. "emoticons": {
  26. "type": "mapping",
  27. "mappings": [
  28. ":) => _happy_",
  29. ":( => _sad_"
  30. ]
  31. }
  32. },
  33. "filter": {
  34. "english_stop": {
  35. "type": "stop",
  36. "stopwords": "_english_"
  37. }
  38. }
  39. }
  40. }
  41. }

内置分析器

我们知道,分词器是分析器的主要组成部分,而 Elasticsearch 内置了多种分词器,那么对应的,也内置了多种分析器。

这里,我们就简单介绍一个内置分析器。

标准分析器

标准分析器(standard analyzer)是默认的分析器。

它由以下几个部分组成:

  • Standard Tokenizer(标准分词器)
  • Filters(过滤器):Standard Token Filter、Lower Case Token Filter 和 Stop Token Filter(默认禁用状态)。

测试分析器

为了便于理解各种分析器是如何工作的,我们可以对分析器进行测试。

测试内置的标准分析器。

  1. GET /_analyze
  2. {
  3. "analyzer": "standard",
  4. "text": "2 Brown-Foxes jumped over the lazy dog's bone."
  5. }

说明: 由于携带交互数据(请求体)的 GET 请求并不被广泛支持,RFC 也并未明文禁止 GET 请求携带交互数据。而 Elasticsearch 的作者更倾向于用 GET 提交查询请求,因此,Elasticsearch 所有的查询 API 同样也支持 POST 方式。

故上面的示例也可以这样写:

  1. POST /_analyze
  2. {
  3. "analyzer": "standard",
  4. "text": "2 Brown-Foxes jumped over the lazy dog's bone."
  5. }

索引时分析器

可以给文档的字段指定具体的分析器。如下:

  1. # 给 my_index/my_type 中的 title 字段指定标准分析器
  2. PUT /my_index
  3. {
  4. "mappings": {
  5. "my_type": {
  6. "properties": {
  7. "title": {
  8. "type": "text",
  9. "analyzer": "standard"
  10. }
  11. }
  12. }
  13. }
  14. }

当 Elasticsearch 对 my_index/my_type 中的文档建立索引时,如果没有指定分析器,就会使用索引库的分析器配置,如果索引库也没有配置分析器,就会使用默认的标准分析器。

搜索时分析器

同样的分析过程也适用于全文搜索时的查询字符串。

例如,match 查询时,要搜索的字符串文本会被切分为单个独立的项。

  1. GET /_search
  2. {
  3. "query": {
  4. "match" : {
  5. "message" : "a quick fox"
  6. }
  7. }
  8. }

分词结果:

“a quick fox” → [a, quick, fox ]

通常,全文搜索将使用和索引字段时相同的分析器来分析查询字符串。

搜索特殊字段的分析器取决于下面的顺序:

  • 查询字符串本身指定的分析器
  • mapping 中的 search_analyzer 选项
  • mapping 中的 analyzer 选项
  • 索引库的 default_search 配置项
  • 索引库的 default 配置项
  • 标准分析器

中文分析器

最常用的中文分析器(analyzer)插件是 ik。

详情请参考它的 GitHub 地址。

参考文献

[1] https://www.elastic.co/guide/en/elasticsearch/reference/5.2/index.html

发表评论

表情:
评论列表 (有 0 条评论,487人围观)

还没有评论,来说两句吧...

相关阅读