一、前言

一个分析器不管是ES内置的还是我们自定义的,都由三个更底层的模块组成:字符过滤器、分词器、分词过滤器。

ES内置的分析器预先把这些模块打包以适合不同的语言和类型的文本。ES也把这些个性化的模块开放了出来,这样我们就能够组合这些模块来定义新的分析器。

二、字符过滤器

字符过滤器接收原始的文本字符流,然后通过添加、删除和修改字符来转换字符流。比如一个字符过滤器可以把印度教阿拉伯语的数字 (٠‎١٢٣٤٥٦٧٨‎٩‎)转换成拉丁语的阿拉伯数字 (0123456789),或者去掉字符串里面HTML元素的<br>标签。

一个分析器可能有零个或者多个字符过滤器,它们顺序发生作用。

三、分词器

分词器接收字符流,将其切分为单个的词条(通常是独立的单词),并将其输出。例如whitespace分词器会将输入的文本根据空格进行切分。它会将文本:"Quick brown fox!"转换为[Quick, brown, fox!]输出。

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

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

四、分词过滤器

一个分词过滤器接收分词流,然后添加、删除或修改分词。例如lowercase 分词过滤器转换所有的分词为小写,一个 stop分词过滤器会从分词流里面删除普通单词(停词,比如the),一个synonym分词过滤器会将分词的同义词添加到分词流。

分词过滤器不允许改变每个分词的位置或者字符偏移量。

一个分析器包含零个或者多个分词过滤器,他们按照顺序生效。

五、分词器的测试

1、analyze api

analyze api是一个极有价值的工具来查看分析器产生的分词结果。在调用api的时候可以在请求里面设置ES内置的分析器(或者联合内置的分词器,分词过滤器,字符过滤器):

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

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

2、位置和字符偏移量

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

3、自定义分析器

另外自定义分析器可以通过在特定索引使用analyze api来测试:

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

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

GET my_index/_analyze 
{
  "field": "my_text", 
  "text":  "Is this déjà vu?"
}

说明:

  1. 定义一个名字叫std_folded的 custom 分析器
  2. 字段my_text使用std_folded分析器
  3. 为了测试该分词器,必须在analyze api中设置索引的名称
  4. 通过分词器的名称来测试该分词器
  5. 通过使用了该分词器的字段来测试该分词器