ES学习记录10——ES分析器1

  • 1. 概述
  • 2. 分析器的本质
  • 3. 分析器简易实操
  • 4. 分析器Analyzers
    • 4.1 配置内置的分析器
      • 4.1.1 标准分析器(Standard Analyzer)
      • 4.1.2 简易分析器(Simple Analyzer)
      • 4.1.3 空格分析器(Whitespace Analyzer)
      • 4.1.4 段词分析器(Stop Analyzer)
      • 4.1.5 关键词分析器(Keyword Analyzer)
      • 4.1.5 模式分析器(Pattern Analyzer)
      • 4.1.6 语言分析器(Language Analyzer)
      • 4.1.7 指纹分析器(Fingerprint Analyzer)
      • 4.1.8 定制分析器(Custom Analyzer)

1. 概述

 ES中“分析”是指转换文本的处理过程(比如一个邮件的正文),将这些文本转换为标记或者术语(即tokensterms),并将这些标记或术语添加到用于搜索的反向索引。分析这个动作在ES中是由分析器(analyzer)完成的,分析器可以是ES内置的,也可以是我们人为根据具体业务为具体的索引定制不同的分析器。

索引分析(查询字符串中的术语与倒排索引中的文本中的术语完全匹配)

 文档中说的是“index time analysis”,“索引时分析”可能更明确一点。例如,下面的一个句子:

"The QUICK brown foxes jumped over the lazy dog!"

在索引时,内置英语分析器将首先把句子转换为不同的标记tokens,将每个token转成小写,删除频繁的停用词(比如the),将术语term缩减为词干(即:foxes–>fox、jumped–>jump、lazy–>lazi),最后,下面的术语将会添加到逆向索引中:

[ quick, brown, fox, jump, over, lazi, dog ]

指定一个索引分析器

 在结构化数据中(即mapping)的每个text字段都可以指定自己的分析器analyzer,如创建:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  // 定义索引的结构化数据
  "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type":     "text",
          "analyzer": "standard"
        }
      }
    }
  }
}
'

索引时,如果没有特别指定分析器analyzer,它将会在索引设置中查找名为default的分析器,如果失败,就默认使用standard分析器。

搜索分析(Search time analysis)

 在匹配查询的全文查询full text queries中,在搜索时将相同的分析过程应用于查询字符串,将查询字符串中的文本转换为与存储在倒排索引中的形式相同的形式。比如,用户想要搜索a quick fox这个字符串,这个字符串将由同样的英语分析器(english analyzer)分析为以下术语(term):[ quick, fox ],即使精确的单词(使用在查询字符串中)没有出现在原始的文本中(即查询字符串中的词干quickfox没有出现在原始文本中,原始文本中出现的QUICKfoxes),因为我们将相同的分析器应用到了文本分析和查询字符串分析过程中,查询字符串中的术语与倒排索引中的文本中的术语完全匹配,那就意味着这些查询字符串将会匹配到我们举例的文档。

指定搜索分析器

 通常情况下,索引和搜索都应该使用同一个分析器,全文查询full text queries就像匹配查询match query使用结构化mapping的形式去查找运用于每个字段的分析器。用于搜索特定字段的分析器通过查找确定:

  • 在查询中指定的分析器analyzer
  • 结构化数据中search_analyzer参数指定的;
  • 结构化数据中analyzer参数指定的;
  • 索引设置中的分析器default_search
  • 索引设置中的分析器default
  • standard标准分析器;

2. 分析器的本质

 无论是ES内置的分析器还是定制的分析器,都只是一个包含三个低级构建块的包:字符过滤器(character filters)、标记生成器(tokenizers)和标记过滤器(token filters),这里面也要注意他们三者的工作顺序为:字符过滤器(数据预处理)–>标记生成器(处理数据,生成token)–>标记过滤器(过滤token以返回)。ES内置的分析器已经事先将适合不同语言和文本类型的构建块打包到这些内置的分析器中,Elasticsearch也公开了各个构建块,以便用户可以使用它们组合得到新的自定义分析器。三个构建块简单情况如下:

  • character filters:字符过滤器将原始文本作为字符流接收,并可以通过添加、删除或更改字符来转换流。比如,一个字符过滤器可以用来将印度-阿拉伯数字(٠‎١٢٣٤٥٦٧٨‎٩‎)转成等价的阿拉伯语-拉丁语中数字(0123456789),或从流中删除等HTML元素。一个分析器中可能存在0个或多个字符过滤器,这些字符过滤器将按序工作;
  • tokenizer:标记生成器tokenizer接收一个字符流,将其分解为单个标记(通常是单个单词),并输出标记(tokens)流。例如,只要看到任何空格,空格标记器(whitespace)就会将文本分成标记,比如他将会把文本Quick brown fox!转换为这些术语:[Quick, brown, fox!]。标记生成器也负责记录每个术语的顺序和位置,也记录该术语所代表的原始单词的开始和结束字符偏移量。每个分析器有且仅有一个标记生成器tokenizer
  • token filter:标记过滤器接受标记流,可以添加、移除或更改标记。比如,一个小写标记过滤器(lowercase)将所有的标记转换为小写,一个段词过滤器(stop)移除标记流中的常用段词(比如the,其实就是常用的冠词、定冠词这类单词),还有一个同义词标记过滤器(synonym)将同义词引入标记流。标记过滤器是不被允许改变每个标记的位置或者字符偏移量的。一个分析器可以有0个或多个标记过滤器,这些标记过滤器按序工作;

所以最终的ES的分析器可以简单定义为tokenizer(有且仅有一个,需要特别指定)、character filters(0或多个,直接在filter中指定,就是过滤器)和token filter(0或多个,直接在filter中指定,就是过滤器)的组合。

3. 分析器简易实操

analyze API 是查看分析器生成的术语(term)的宝贵工具,内置的分析器可以在请求行中指定,比如:

// 栗子1:指定分析器(只有空格标记生成器)和文本进行分析
curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "whitespace",
  "text":     "The quick brown fox."
}
'

// 栗子1:分析结果
{
    "tokens": [
        {
            "token": "The",
            "start_offset": 0,
            "end_offset": 3,
            "type": "word",
            "position": 0
        },
        {
            "token": "quick",
            "start_offset": 4,
            "end_offset": 9,
            "type": "word",
            "position": 1
        },
        {
            "token": "brown",
            "start_offset": 10,
            "end_offset": 15,
            "type": "word",
            "position": 2
        },
        {
            "token": "fox.",
            "start_offset": 16,
            "end_offset": 20,
            "type": "word",
            "position": 3
        }
    ]
}

// 栗子2:指定分析器(包含1个标准标记生成器和2个标记过滤器)和文本进行分析
curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "tokenizer": "standard",
  // asciifolding过滤器是用于去除特殊字符
  "filter":  [ "lowercase", "asciifolding" ],
  "text":      "Is this déja vu?"
}
'

// 栗子2:分析结果
{
    "tokens": [
        {
            "token": "is",
            "start_offset": 0,
            "end_offset": 2,
            "type": "",
            "position": 0
        },
        {
            "token": "this",
            "start_offset": 3,
            "end_offset": 7,
            "type": "",
            "position": 1
        },
        {
            "token": "deja",
            "start_offset": 8,
            "end_offset": 12,
            "type": "",
            "position": 2
        },
        {
            "token": "vu",
            "start_offset": 13,
            "end_offset": 15,
            "type": "",
            "position": 3
        }
    ]
}

注意】位置和字符偏移:由于可以从 analyze API 的输出结果中看到,就像之前所提及的那样,分析器不仅仅将单词转换为术语(trems),它们同样也记录每个术语的顺序和相对位置以及每个术语在原始文本中的始、末字符的偏移量(用于突出显示搜索片段)。比如上述栗子2中的结果,术语is的信息如下:

// is术语中开始字符“i”的偏移量在原始文本“Is this déja vu?”中的偏移量为0
"start_offset": 0,
// is术语中的末尾字符“s”的偏移量在原始文本“Is this déja vu?”中的偏移量为2
"end_offset": 2,
"type": "",
// is术语在原始文本“Is this déja vu?”中的偏移量为0
"position": 0

 当然,在特定索引上执行 analyze API 时,可以引用自定义的分析器,比如:

先创建一个新的索引,同时指定一个定制的分析器:

// 这里创建索引时先将之前栗子中已创建的my_index索引删除
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        // 定义一个定制的分析器,名字指定为“std_folded”
        "std_folded": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": ["lowercase","asciifolding"]
        }

      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "my_text": {
          "type": "text",
          // 指定“my_text”字段使用上面自定义的分析器“std_folded”
          "analyzer": "std_folded"
        }
      }
    }
  }
}
'

如果要引用上面自定义的分析器,可以这么干:

// 为了使用上述定义的分析器,必须指定特定的索引名字
curl -X GET "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d'
{
  // 通过分析器名字引用分析器
  "analyzer": "std_folded",
  "text":     "Is this déjà vu?"
}
'
curl -X GET "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d'
{
  // 引用my_text字段使用的分析器
  "field": "my_text",
  "text":  "Is this déjà vu?"
}
'

结果和之前的2个栗子一样,参考前面的。

4. 分析器Analyzers

 ES配置了大量内置的分析器,我们可以不怎么自己去配置就可以使用这些分析器,主要如下:

  • Standard Analyzer:标准分析器(参数表示为standard)可以将文本以单词边界划分术语terms,采用的是由Unicode文本分段算法,它可以删除了大多数标点符号,将术语转成小写,支持删除段词(它仅仅是支持删除段词,这个功能需要自己配);
  • Simple Analyzer:只要遇到非字母的字符,简单分析器(参数表示为simple)就会将文本划分为术语,将术语转成小写;
  • Whitespace Analyzer:只要遇到空格字符,空格分析器(参数表示为whitespace)就会将文本划分为术语,不会将术语转成小写
  • Stop Analyzer:段词分词器(参数表示为simple)和标准分析器standard一样,遇到非字母字符就分割,也支持删除段词;
  • Keyword Analyzer:关键字分析器(参数表示为keyword)是一个“空”分析器,可以接受给定的任何文本,并输出与单个术语完全相同的文本;
  • Pattern Analyzer:模式分析器(参数表示为pattern)使用正则表达式将文本拆分为术语,它支持小写术语和段词;
  • Language Analyzer:Elasticsearch提供许多特定于语言的分析器,如英语分析器(参数表示为english)或法语分析器(参数表示为french);
  • Fingerprint Analyzer:指纹分析器(参数表示为fingerprint)是一种创建可用于重复检测的指纹专业分析器;

 自定义分析器,其实和之前介绍的一样,透过本质,我们可以通过适当的字符过滤器、标记生成器以及标记过滤器的组合完成一个自定义的分析器。

4.1 配置内置的分析器

 内置的分析器可以无配置直接使用,但里面有部分内置分析器是支持配置一些选项改变它们部分行为的,比如,标准分析器standard可以配置支持段词:

PUT my_index
{
  "settings": {
    "analysis": {
      // 在standard分析器的基础上配置段词得到一个自定分析器 std_english
      "analyzer": {
        "std_english": {
          "type":      "standard",
          "stopwords": "_english_"
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "my_text": {
          "type":     "text",
          // 直接指定 my_text 字段使用 standard 分析器,没有配置删除段词
          "analyzer": "standard",
          "fields": {
            "english": {
              "type":     "text",
              "analyzer": "std_english"
            }
          }
        }
      }
    }
  }
}

测试样例:

POST my_index/_analyze
{
   // 指定使用 my_text 字段的分析器,即 standard 分析器
  "field": "my_text",
  "text": "The old brown cow"
}

POST my_index/_analyze
{
  // 指定使用 my_text.english 字段的分析器,即 std_english 分析器,即可以删除段词的 standard 分析器
  "field": "my_text.english",
  "text": "The old brown cow"
}

结果为[the, old, brown, cow][old, brown, cow]

4.1.1 标准分析器(Standard Analyzer)

standard分析器是默认的分析器,如果没有特别指定分析器那就是使用的标准分析器,它提供了基于语法的标记生成方法(之前已经提过,它是基于Unicode文本分割算法),可以用于大部分的语言。比如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog\u0027s bone."
}
'

分析器出来的结果就是[the, 2, quick, brown, foxes, jumped, over, the, lazy, dog's, bone]

standard分析器是可配置的,可以接受的参数有:

  • max_token_length:指定标记的最大长度,如果一个标记超过了该参数设置的值,则用这个参数值直接分割(不论是否到标记),默认是255;
  • stopwords:段词,比如像之前内置就定义了英语段词_english_或者包含一系列段词的数组,默认是\_none_
  • stopwords_path:表示一个包含停用词的文件路径;

下面是一个小栗子:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        // 定义一个分析器,名字为 my_english_analyzer
        "my_english_analyzer": {
          "type": "standard",
          // 配置最大标记长度
          "max_token_length": 5,
          // 指定段词为英语段词
          "stopwords": "_english_"
        }
      }
    }
  }
}
'

测试:

curl -X POST "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d'
{
  "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],因为jumped是6个字符,超过了标记最大长度max_token_length的值,那直接分割成jumped两个标记(token)。

standard分析器主要组成部分有:

  • Standard Tokenizer:这是standard分析器的标记生成器;
  • Standard Token Filter:这是standard分析器的标记过滤器;
  • Standard Case Token Filter:这是standard分析器的标记过滤器(将标记转成小写);
  • Stop Token Filter:段词标记过滤器,默认不开启;

如果需要在配置参数之外自定义标准分析器,则需要将其重新创建自定义分析器并通常通过添加标记过滤器进行修改,这些行为将会重新创建standard分析器,可以直接在创建索引时直接创建,如:

curl -X PUT "localhost:9200/standard_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        // 定义一个基于standard的分析器 rebuilt_standard
        "rebuilt_standard": {
          "tokenizer": "standard",
          "filter": [
            "standard",
            "lowercase"
          ]
        }
      }
    }
  }
}
'

4.1.2 简易分析器(Simple Analyzer)

simple分析器只要碰到非字母字符就分割文本,所有的术语全部转成小写,比如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "simple",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
'

遇到2(非字母)分割一下、遇到空格分割一次、遇到'分割一次,最后得到的结果为[the, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone]

simple分析器是不可配置的,它的组成没有其他的,就一个标记生成器 Lower Case Tokenizer 。如果要定制simple分析器,需要像custom类型一样重建这个分析器然后再修改,通常是添加一些标记过滤器,比如:

curl -X PUT "localhost:9200/simple_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "rebuilt_simple": {
          "tokenizer": "lowercase",
          "filter": [
              // 根据需求往里添加标记过滤器
              "xxx1",
              "xxx2"
          ]
        }
      }
    }
  }
}
'

4.1.3 空格分析器(Whitespace Analyzer)

whitespace分析器只要遇到空格字符就分割文本,比如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "whitespace",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
'

之前提过whitespace分析器不会将标记转成小写,结果为:[The, 2, QUICK, Brown-Foxes, jumped, over, the, lazy, dog's, bone.]

whitespace分析器也是不可配置的,它里面就一个 Whitespace Tokenizer 标记生成器。如果想定制whitespace分析器,需要将分析器的类型指定为custom进行重建修改,通常也就往里面加一些标记过滤器,比如:

curl -X PUT "localhost:9200/whitespace_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "rebuilt_whitespace": {
          "tokenizer": "whitespace",
          "filter": [
              // 根据需求往里添加标记过滤器
              "xxx1",
              "xxx2"
          ]
        }
      }
    }
  }
}
'

4.1.4 段词分析器(Stop Analyzer)

stop分析器和simple分析器一样,遇到非字母字符就分割,但它支持删除段词(我理解下来就是一些冠词),默认使用英语段词_english_。比如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "stop",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog\u0027s bone."
}
'

stop分析器是可配置的,可接受的参数有:

  • stopwords:预先定义的段词,和英语段词_english_或一个包含一系列段词的数组是一个意思,默认是_english_
  • stopwords_path:表示一个包含段词文件的路径,这个路径是相对与ES的配置根目录config而言的;

下面是一个小栗子:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_stop_analyzer": {
          "type": "stop",
          // 此时指定段词只有 the 和 over 两个,默认的 _english_ 失效
          "stopwords": ["the", "over"]
        }
      }
    }
  }
}
'

使用下面的进行测试:

curl -X POST "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "my_stop_analyzer",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
'

将非字母字符和the以及over作为段词,最终的结果结果为:[quick, brown, foxes, jumped, lazy, dog, s, bone]

stop分析器主要是由一个标记生成器 Lower Case Tokenizer 和一个标记过滤器 Stop Token Filter 组成,如果需要在配置参数之外的自定义stop分析器,则需要将其重新创建自定义分析器并通常通过添加标记过滤器进行修改,这些行为将会重新创建standard分析器,可以直接在创建索引时直接创建,如:

PUT /stop_example
{
  "settings": {
    "analysis": {
      "filter": {
        "english_stop": {
          "type":       "stop",
          // 指定段词为英语段词
          "stopwords":  "_english_"
        }
      },
      "analyzer": {
        "rebuilt_stop": {
          "tokenizer": "lowercase",
          "filter": [
            "english_stop"     
          ]
        }
      }
    }
  }
}

注:上述stop分析器中默认的段词是可以被stopwordsstopwords_path参数覆盖的。

4.1.5 关键词分析器(Keyword Analyzer)

keyword分析器是一个内部为空的分析器,它会返回和输入的一模一样的字符串作为标记(token)。比如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "keyword",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog\u0027s bone."
}
'

根据上面所说可知,直接返回的结果为:[The 2 QUICK Brown-Foxes jumped over the lazy dog's bone.],直接返回输入的文本作为单独一个token

keyword分析器也是不可配置的,它内部就一个 Keyword Tokenizer 标记生成器。如果想定制keyword分析器,需要将分析器的类型指定为custom进行重建修改,通常也就往里面加一些标记过滤器,比如:

curl -X PUT "localhost:9200/keyword_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "rebuilt_keyword": {
          "tokenizer": "keyword",
          "filter": [
            // 根据需求往里添加标记过滤器
            "xxx1",
            "xxx2"         
          ]
        }
      }
    }
  }
}
'

4.1.5 模式分析器(Pattern Analyzer)

pattern分析使用正则表达式(使用的是Java正则表达式,注意避免病理正则表达式,可能导致搜索缓慢甚至导致StackOverflowError或运行的节点闪退)将文本分割为术语。正则表达式应该匹配token separators而不是标记本身,爱分析器中的默认正则表达式为\W+(即匹配1或多个非单词字符,就是除了字母和数字外的所有字符,等价于[^A-Za-z0-9_])。比如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "pattern",
  "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]

pattern分析器是可配置,可接受如下的参数:

  • pattern:一个 Java 正则表达式,默认是\W+
  • flags:Java正则表达式flags,多个标志之间是管道分开的(如CASE_INSENSITIVE|COMMENTS);
  • lowercase:表示是否将术语转成小写,默认为true
  • stopwords:表示预先定义好的段词,比如英语段词_english_或一个包含一系列段词的数组,默认为\_none_(即没有设段词);
  • stopwords_path:表示一个包含段词文件的路径;

下面是一个小栗子:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
		// 自定义一个分析器 my_email_analyzer
        "my_email_analyzer": {
          "type":      "pattern",
		  // 正则表达式,匹配非单词字符和下划线
          "pattern":   "\\W|_",
		  // 将分割后的术语全部转成小写
          "lowercase": true
        }
      }
    }
  }
}
'

验证:

curl -X POST "localhost:9200/my_index/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "my_email_analyzer",
  "text": "[email protected]"
}
'

直接使用非单词字符和下划线作为分割标记,最终的结果为:[john, smith, foo, bar, com]。当然还可以使用正则实现更加复杂的分割方式,比如按照Java中的驼峰命名的方式分割:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "camel": {
          "type": "pattern",
          "pattern": "([^\\p{L}\\d]+)|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[\\p{L}&&[^\\p{Lu}]])(?=\\p{Lu})|(?<=\\p{Lu})(?=\\p{Lu}[\\p{L}&&[^\\p{Lu}]])"
        }
      }
    }
  }
}
'

当指定上述定义的camel来分割文本MooseX::FTPClass2_beta,结果为[moose, x, ftp, class, 2, beta],这里对上述正则做一个简单的说明:

  ([^\p{L}\d]+)                 # 吞下非字母和非数字的字符,
| (?<=\D)(?=\d)                 # 或非数字后面跟数字,
| (?<=\d)(?=\D)                 # 或数字后面跟非数字,
| (?<=[ \p{L} && [^\p{Lu}]])(?=\p{Lu})    # 或小写字母后面跟大写字母,
| (?<=\p{Lu})(?=\p{Lu}[\p{L}&&[^\p{Lu}]]) # 或大写字母后面跟大写再跟小写

pattern分析器的组成:一个 Pattern Tokenizer 标记生成器、一个 Lower Case Token Filter 标记过滤器、一个 Stop Token Filter 段词过滤器(默认没有开启);如果想定制pattern分析器,需要将分析器的类型指定为custom进行重建修改,通常也就往里面加一些标记过滤器,比如:

curl -X PUT "localhost:9200/pattern_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
	  // 配置标记生成器
      "tokenizer": {
        "split_on_non_word": {
          "type":       "pattern",
		  // 默认模式为 \W+ 匹配非单词字符,可自己修改
          "pattern":    "\\W+" 
        }
      },
      "analyzer": {
        "rebuilt_pattern": {
          "tokenizer": "split_on_non_word",
          "filter": [
            "lowercase"       
          ]
        }
      }
    }
  }
}
'

4.1.6 语言分析器(Language Analyzer)

 ES提供了一套针对特殊语言文本的分析器,之前用到的_english_是对英语段词的分析器,ES支持的语言分析器主要有:

arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english, finnish, french, galician, german, greek, hindi, hungarian, indonesian, irish, italian, latvian, lithuanian, norwegian, persian, portuguese, romanian, russian, sorani, spanish, swedish, turkish, thai

 所有分析器都支持在配置内设置自定义的段词stopwords,或通过设置stopwords_path使用外部段词文件。需要排除词干中的单词,stem_exclusion参数允许用户指定不应该被阻止的小写单词数组。在内部,这个功能是通过添加keyword_marker标记过滤器并将keywords设置为stem_exclusion参数的值来实现的。下面的分析器支持设置自定义的stem_exclusion数组:

arabic, armenian, basque, bengali, bulgarian, catalan, czech, dutch, english, finnish, french, galician, german, hindi, hungarian, indonesian, irish, italian, latvian, lithuanian, norwegian, portuguese, romanian, russian, sorani, spanish, swedish, turkish

 如果想定制内部的语言分析器,需要将分析器的类型指定为custom进行重建修改,如果不打算排除被阻止的单词(相当于上面的stem_exclusion参数),那么应该从自定义分析器配置中删除keyword_marker标记过滤器。

下面是阿拉伯语言分析器的小栗子(其他语言类似),需要将分析器的类型指定为custom进行重建修改:

curl -X PUT "localhost:9200/arabic_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "filter": {
        "arabic_stop": {
          "type":       "stop",
		  // 可以自定义或使用 stopwords_path 覆盖
          "stopwords":  "_arabic_" 
        },
        "arabic_keywords": {
          "type":       "keyword_marker",
		  // 
          "keywords":   ["مثال"] 
        },
        "arabic_stemmer": {
          "type":       "stemmer",
          "language":   "arabic"
        }
      },
      "analyzer": {
        "rebuilt_arabic": {
          "tokenizer":  "standard",
          "filter": [
            "lowercase",
            "decimal_digit",
            "arabic_stop",
            "arabic_normalization",
            "arabic_keywords",
            "arabic_stemmer"
          ]
        }
      }
    }
  }
}
'

其他语言分析器的样例参看Language Analyzersedit

4.1.7 指纹分析器(Fingerprint Analyzer)

fingerprint分析器是基于指纹识别算法(由OpenRefine项目用于协助聚类)实现的。输入文本是小写的、规范化的以删除扩展字符,经过排序、删除重复数据并连接成单个标记token。如果配置了段词列表,则也会删除段词。如:

curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{
  "analyzer": "fingerprint",
  "text": "Yes yes, Gödel said this sentence is consistent and."
}
'

将重复的yes去除只留一个,然后将剩余的单词按字母表排序最终得到的结果为:[and consistent godel is said sentence this yes]

fingerprint分析器是可配置的,可接受的参数有:

  • separator:表示连接术语的字符,默认为空格符;
  • max_output_size:表示输出标记的最大长度,默认为255,如果标记大于该参数直接按该参数的值分割;
  • stopwords:表示预先定义好的段词,比如英语段词_english_或一个包含一系列段词的数组,默认为\_none_(即没有设段词);
  • stopwords_path:表示一个包含段词文件的路径;

下面是一个小栗子:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
		// 自定义配置指纹分析器
        "my_fingerprint_analyzer": {
          "type": "fingerprint",
		  // 将段词指定为英文段词
          "stopwords": "_english_"
        }
      }
    }
  }
}
'

使用上述的分析器my_fingerprint_analyzer分析文本Yes yes, Gödel said this sentence is consistent and.,由于配置了英语段词,所以在原来的结果上还要去除英语段词,得到的结果为:[consistent godel said sentence yes]

fingerprint分析器组成: Standard Tokenizer 标记生成器、Lower Case Token Filter 小写标记过滤器、ASCII Folding Token Filter 过滤器(去除特殊字符)、Stop Token Filter 段词标记过滤器、Fingerprint Token Filter 过滤器。上述提及的过滤器都是按序执行工作的。如果想定制fingerprint分析器,需要将分析器的类型指定为custom进行重建修改,通常就是往里面加一些过滤器,如:

curl -X PUT "localhost:9200/fingerprint_example" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "rebuilt_fingerprint": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding",
            "fingerprint",
            // 根据需求往里添加标记过滤器
            "xxx1",
            "xxx2"
          ]
        }
      }
    }
  }
}
'

4.1.8 定制分析器(Custom Analyzer)

 有一些场景,ES内置的分析器并不能满足需求,这时可以创建一个custom分析器,创建的原则就是立足分析器的本质进行组合就可以了,分析器的本质:

  • 有且仅有1个标记生成器(tokenizer);
  • 0或多个标记过滤器(token filter);
  • 0或多个字符过滤器(character filter);

custom分析器可接受的参数有:

  • tokenizer:表示内置或定制的标记生成器,必选参数;
  • char_filter:表示一个包含内置或定制字符过滤器的数组,可选参数;
  • filter:表示一个包含内置或定制的标记过滤器数组,可选参数;
  • position_increment_gap:当索引文本的值是一个数组时,Elasticsearch会在一个值的最后一个术语和下一个值的第一个术语之间插入一个虚假的“间隙”,以确保短语查询与来自不同数组元素的两个术语不匹配,默认为100;

下面是一个小栗子:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
		  // 将 type 指定为 custom,告诉ES我们正在自定义一个分析器
          "type":      "custom", 
          "tokenizer": "standard",
          "char_filter": [
            "html_strip"
          ],
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  }
}
'

上述定制了一个自定义分析器,组合为:standard标记生成器(tokenizer)、html_strip字符过滤器、lowercaseasciifolding标记过滤器。用上述的自定义的分析器my_custom_analyzer分析文本Is this déjà vu?,得到的结果为:[is, this, deja, vu]。当然还可以自定义更加复杂的分析器,下面是一个复杂的小栗子:

curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
		// 自定义分析器 my_custom_analyzer
        "my_custom_analyzer": {
          "type": "custom",
          "char_filter": [
			// 指定字符过滤器为 emoticons,表情符号过滤器
            "emoticons" 
          ],
		  // 指定标记生成器为 punctuation 
          "tokenizer": "punctuation", 
          "filter": [
            "lowercase",
			// 指定标记过滤器为 english_stop 
            "english_stop" 
          ]
        }
      },
      "tokenizer": {
        "punctuation": { 
          "type": "pattern",
          "pattern": "[ .,!?]"
        }
      },
      "char_filter": {
        "emoticons": { 
          "type": "mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": {
        "english_stop": { 
          "type": "stop",
          "stopwords": "_english_"
        }
      }
    }
  }
}
'

用以上自定义的分析器my_custom_analyzer分析文本I'm a :) person, and you?,得到的结果为:[i'm, _happy_, person, you]

你可能感兴趣的:(#,ES,Elasticsearch)