虽然Elasticsearch带有一些现成的分析器,然而在分析器上Elasticsearch 真正强大之处在于,你可以通过在一个适合你的特定数据的设置之中组合字符过滤器、分词器、词汇单元过滤器来创建自定义的分析器。

分析与分析器 我们说过,一个 分析器 就是在一个包里面组合了三种函数的一个包装器, 三种函数按照顺序被执行:

字符过滤器

字符过滤器,用来整理一个尚未被分词的字符串。例如,如果我们的文本是HTML格式的,他会包含像

或者

这样的HTML 标签,这些标签时我们不想索引的。我们可以使用html清除字符过滤器 来移除所有的HTML标签,并且像把Á 转换为相应的Unicode 字符Á 这样,转换HTML 实体。

一个分析器可能有0个或者多个字符过滤器。

分词器

一个分析器 必须有一个唯一的分词器。分词器把字符串分解成单个词条或者词汇单元。标准 分析器里使用的 标准分词器 把一个字符串根据单词边界分解成单个词条,并且移除掉大部分的标点符号,然而还有其他不同行为的分词器存在。

例如, 关键词分词器 完整的输出接收到的同样的字符串,并不做任何分词。 空格分词器 只根据空格分割文本 。 正则分词器 根据匹配正则表达式来分割文本 。

词元过滤器

经过分词,作为结果的词单元会按照指定的顺序通过指定的词单元过滤器。

词单元过滤器可以修改、添加或者移除词单元。我们已经提到过 lowercasestop词过滤器 ,但是在 Elasticsearch 里面还有很多可供选择的词单元过滤器。 词干过滤器 把单词 遏制 为 词干。 ascii_folding过滤器移除变音符,把一个像 “très” 这样的词转换为 “tres” 。 ngramedge_ngram词单元过滤器 可以产生 适合用于部分匹配或者自动补全的词单元。

深入搜索,我们讨论了在哪里使用,以及怎样使用分词器和过滤器。但是首先,我们需要解释一下怎样创建自定义的分析器。

创建一个自定义分析器

和我们之前配置es_std 分析器一样,我们可以在analysis下的相应位置设置字符过滤器、分词器和词单元过滤器:

  1. PUT /my_index
  2. {
  3. "settings": {
  4. "analysis": {
  5. "char_filter": { ... custom character filters ... },
  6. "tokenizer": { ... custom tokenizers ... },
  7. "filter": { ... custom token filters ... },
  8. "analyzer": { ... custom analyzers ... }
  9. }
  10. }
  11. }

作为示范,让我们一起来创建一个自定义分析器吧,这个分析器可以做到下面的这些事:

  1. 使用html清除 字符过滤器移除HTML 部分。
  2. 使用一个自定义的映射 字符过滤器把 & 替换为 and :

    1. "char_filter": {
    2. "&_to_and": {
    3. "type": "mapping",
    4. "mappings": [ "&=> and "]
    5. }
    6. }
  3. 使用标准分词器分词。

  4. 小写词条,使用小写词过滤器处理。
  5. 使用自定义 停止词过滤器移除自定义的停止词列表中包含的词:
    1. "filter": {
    2. "my_stopwords": {
    3. "type": "stop",
    4. "stopwords": [ "the", "a" ]
    5. }
    6. }

我们的分析器定义用我们之前已经设置好的自定义过滤器组合了已经定义好的分词器和过滤器:

  1. "analyzer": {
  2. "my_analyzer": {
  3. "type": "custom",
  4. "char_filter": [ "html_strip", "&_to_and" ],
  5. "tokenizer": "standard",
  6. "filter": [ "lowercase", "my_stopwords" ]
  7. }
  8. }

汇总起来,完整的 创建索引 请求看起来应该像这样:

  1. PUT /my_index
  2. {
  3. "settings": {
  4. "analysis": {
  5. "char_filter": {
  6. "&_to_and": {
  7. "type": "mapping",
  8. "mappings": [ "&=> and "]
  9. }},
  10. "filter": {
  11. "my_stopwords": {
  12. "type": "stop",
  13. "stopwords": [ "the", "a" ]
  14. }},
  15. "analyzer": {
  16. "my_analyzer": {
  17. "type": "custom",
  18. "char_filter": [ "html_strip", "&_to_and" ],
  19. "tokenizer": "standard",
  20. "filter": [ "lowercase", "my_stopwords" ]
  21. }}
  22. }}}

索引被创建以后,使用analyze API 来测试这个新的分析器:

  1. GET /my_index/_analyze?analyzer=my_analyzer
  2. The quick & brown fox

下面的缩略结果展示出我们的分析器正在正确地运行:

  1. {
  2. "tokens" : [
  3. { "token" : "quick", "position" : 2 },
  4. { "token" : "and", "position" : 3 },
  5. { "token" : "brown", "position" : 4 },
  6. { "token" : "fox", "position" : 5 }
  7. ]
  8. }

这个分析器现在是没有多大用处的,除非我们告诉 Elasticsearch在哪里用上它。我们可以像下面这样把这个分析器应用在一个 string 字段上:

  1. PUT /my_index/_mapping/my_type
  2. {
  3. "properties": {
  4. "title": {
  5. "type": "string",
  6. "analyzer": "my_analyzer"
  7. }
  8. }
  9. }