转:https://blog.csdn.net/u011250186/article/details/125704364

1 简介

  把输入的文本块按照一定的策略进行分解,并建立倒排索引。在Lucene的架构中,这个过程由分析器(analyzer)完成

  这里我们先来看下elasticsearch官方文档中的一段介绍

  一个analyzer即分析器,无论是内置的还是自定义的,只是一个包含character filters(字符过滤器)、 tokenizers(分词器)、token filters(令牌过滤器)三个细分模块的包。

  内置分析器将这些构建块预先打包成适用于不同语言和文本类型的分析器。Elasticsearch 还公开了各个构建块,以便将它们组合起来定义新的自定义分析器

 

2 三个主要组成

2.1 字符过滤器character filter

  字符过滤器用于接收原始文本字符的流,并且可以通过添加,移除,或改变字符来转变原始字符流。例如,字符过滤器可用于将印度-阿拉伯数字 (٠ ١٢٣٤٥٦٧٨ ٩ ) 转换为它们的阿拉伯-拉丁数字 (0123456789),或从流中去除像<b>这种 HTML 元素等。

  分析器可能有零个或多个 字符过滤器,它们在分析器中按顺序生效使用。

 

2.2 分词器tokenizer

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

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

  一个分析器必须有且只有一个分词器

 

2.3 token过滤器token filters

  token过滤器接收令牌流,并且可以添加,删除或改变token。例如,lowercasetoken过滤器将所有token转换为小写, stoptoken过滤器从token流中删除常用词(停用词)the,而 synonym token过滤器将同义词引入token流中。

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

  词干提取一般使用词干提取token filters。token filter一般会生成对应的token graphs,这个graph能详细标识一个text文本被分成的token以及这些token之间的关系。

  分析器可能有零个或多个 token过滤器,它们按顺序应用生效

 

3 文本分词发生的地方

  创建索引:当索引文档字符类型为text时,在建立索引时将会对该字段进行分词。

  搜索:当对一个text类型的字段进行全文检索时,会对用户输入的文本进行分词

 

4 默认分词器

  默认ES使用standard analyzer,如果默认的分词器无法符合你的要求,可以自己配置

 

5 查看分词结果语法(测试分词)

5.1 基本用法

1)查询

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

 

2)返回结果

{
  "tokens" : [
    {
      "token" : "the",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "quick",
      "start_offset" : 4,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "fox",
      "start_offset" : 16,
      "end_offset" : 19,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

 

5.2 更多用法

  同时你也可以按照下面的规则组合使用

  • 0个或者多个character filters
  • 一个tokenizer
  • 0个或者多个token filters

 

1)查询

POST _analyze
{
  "tokenizer": "standard",
  "filter": ["lowercase"],
  "text": "The quick brown fox"
}

 

2)结果

{
  "tokens" : [
    {
      "token" : "the",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "quick",
      "start_offset" : 4,
      "end_offset" : 9,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 10,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "fox",
      "start_offset" : 16,
      "end_offset" : 19,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

  与之前不同的是,它会将切分的词进行小写处理。这是因为添加了一个lowercasetoken filter,它会将分词的词进行小写处理

 

6 创建mapping时指定分词器示例

  对索引和查询都有效

  如下,指定ik分词的配置

PUT mytest5
{
  "mappings": {
      "properties": {
        "content": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        }
      }
  }
}

  如果报下面错误,需要安装ik分词器

  ik分词器安装:https://www.cnblogs.com/jthr/p/17075759.html

analyzer [ik_max_word] not found for field [name] kibana

 

7 配置内置分词器

  内置的分词器无需任何配置我们就可以使用。但是我们可以修改内置的部分选项修改它的行为

 

1)示例

  下面的例子中,我们配置分词器std_english,它使用的分词器为standard分词器,他的停词列表设置为_english_.然后字段my_text使用的是standard分词器,而字段my_text.english使用的是我们配置的std_english

DELETE my_index
 
PUT /my_index?pretty
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_english": { 
          "type":      "standard",
          "stopwords": "_english_"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type":     "text",
        "analyzer": "standard", 
        "fields": {
          "english": {
            "type":     "text",
            "analyzer": "std_english" 
          }
        }
      }
    }
  }
}
 

 

2)测试分词

POST /my_index/_analyze?pretty
{
  "field": "my_text", 
  "text": "The old brown cow"
}

  结果

{
  "tokens" : [
    {
      "token" : "the",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "old",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 8,
      "end_offset" : 13,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "cow",
      "start_offset" : 14,
      "end_offset" : 17,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

  测试分词

POST /my_index/_analyze?pretty
{
  "field": "my_text.english", 
  "text": "The old brown cow"
}

  结果

{
  "tokens" : [
    {
      "token" : "old",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "brown",
      "start_offset" : 8,
      "end_offset" : 13,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "cow",
      "start_offset" : 14,
      "end_offset" : 17,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

  结果1和2的区别为,结果2中的停词The被删除,而结果1中的并没有。这是因为my_text.english配置了停词

 

8 创建自定义分词器

8.1 简介

 

  当内置的分词器无法满足需求时,可以创建custom类型的分词器。

  • tokenizer:内置或定制的tokenizer.(必须)
  • char_filter:内置或定制的char_filter(非必须)
  • filter:内置或定制的token filter(非必须)
  • position_increment_gap:当值为文本数组时,设置改值会在文本的中间插入假空隙。设置该属性,对与后面的查询会有影响。默认该值为100

 

8.2 示例

  下面的示例中定义了一个名为my_custom_analyzer的分词器,该分词器的typecustomtokenizerstandardchar_filterhmtl_strip,filter定义了两个分别为:lowercaseasciifolding

DELETE my_index
 

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer":{
          "type":"custom",
          "tokenizer":"standard",
          "char_filter":["html_strip"],
          "filter":["lowercase","asciifolding"]
        }
      }
    }
  }
}

   分词测试

POST my_index/_analyze
{
  "text": "Is this <b>déjà vu</b>?",
  "analyzer": "my_custom_analyzer"
}

  结果

{
  "tokens" : [
    {
      "token" : "is",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "this",
      "start_offset" : 3,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "deja",
      "start_offset" : 11,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "vu",
      "start_offset" : 16,
      "end_offset" : 22,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

 

9 创建索引自定义分词器并指定给字段示例

1)自定义分词器并为字段指定该分词器

  下面操作我们自定义了一个分词器叫做std_folded,它的tokenizerstandard,同时有两个token filter分别为:lowercaseasiciifolding

  我们在定义mapping时,设置了一个字段名为my_text,它的类型为text,我们指定它使用的分词器为我们定义的std_folded.在分词测试中

PUT /my_index?pretty
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_folded": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type": "text",
        "analyzer": "std_folded" 
      }
    }
  }
}

 

2)测试下该分词器的分词

GET /my_index/_analyze?pretty
{
  "analyzer": "std_folded", 
  "text":     "Is this déjà vu?"
}

  返回结果

{
  "tokens" : [
    {
      "token" : "is",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "this",
      "start_offset" : 3,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "deja",
      "start_offset" : 8,
      "end_offset" : 12,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "vu",
      "start_offset" : 13,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 3
    }
  ]
}

 

10 创建索引时指定分词器

10.1 简介

  如果设置手动设置了分词器,ES将按照下面顺序来确定使用哪个分词器:

  • 先判断字段是否有设置分词器,如果有,则使用字段属性上的分词器设置
  • 如果设置了analysis.analyzer.default,则使用该设置的分词器
  • 如果上面两个都未设置,则使用默认的standard分词器

 

10.2 为字段指定分词器

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

 

10.3 为索引设置默认分词器

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default":{
          "type":"simple"
        }
      }
    }
  }
}

 

11 搜索时如何确定分词器

11.1 简介

  在搜索时,通过下面参数依次检查搜索时使用的分词器:

  • 搜索时指定analyzer参数
  • 创建mapping时指定字段的search_analyzer属性
  • 创建索引时指定settinganalysis.analyzer.default_search
  • 查看创建索引时字段指定的analyzer属性

  如果上面几种都未设置,则使用默认的standard分词器。

  

11.2 搜索时指定analyzer查询参数

GET my_index/_search
{
  "query": {
    "match": {
      "message": {
        "query": "Quick foxes",
        "analyzer": "stop"
      }
    }
  }
}

 

11.3 指定字段的seach_analyzer

PUT my_index
{
  "mappings": {
    "properties": {
      "title":{
        "type":"text",
        "analyzer": "whitespace",
        "search_analyzer": "simple"
      }
    }
  }
}

  

11.4 指定索引的默认搜索分词器

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default":{
          "type":"simple"
        },
        "default_seach":{
          "type":"whitespace"
        }
      }
    }
  }
}

上面指定创建索引时使用的默认分词器为simple分词器,而搜索的默认分词器为whitespace分词器

 

12 更多官网介绍

1)如何在elasticsearch中使用分词器

2)常用的中文分词器ik 

3)拼音分词器

4)分析器analyzer

5)字符过滤器character filter

6)分词器tokenizer

7)token过滤器token filters

8)自定义分析器