• 自定义分析器
  • 创建自定义分析器

    自定义分析器

    虽然 Elasticsearch 内置了一系列的分析器,但是真正的强大之处在于定制你自己的分析器。你可以通过在配置文件中组合字符过滤器,分词器和标记过滤器,来满足特定数据的需求。

    在 【分析器介绍】 中,我们提到 分析器 是三个顺序执行的组件的结合(字符过滤器,分词器,标记过滤器)。

    字符过滤器

    字符过滤器是让字符串在被分词前变得更加“整洁”。例如,如果我们的文本是 HTML 格式,它可能会包含一些我们不想被索引的 HTML 标签,诸如 <p><div>

    我们可以使用 html_strip 字符过滤器 来删除所有的 HTML 标签,并且将 HTML 实体转换成对应的 Unicode 字符,比如将 &Aacute; 转成 Á

    一个分析器可能包含零到多个字符过滤器。

    分词器

    一个分析器 必须 包含一个分词器。分词器将字符串分割成单独的词(terms)或标记(tokens)。standard 分析器使用 standard 分词器将字符串分割成单独的字词,删除大部分标点符号,但是现存的其他分词器会有不同的行为特征。

    例如,keyword 分词器输出和它接收到的相同的字符串,不做任何分词处理。[whitespace 分词器]只通过空格来分割文本。[pattern 分词器]可以通过正则表达式来分割文本。

    标记过滤器

    分词结果的 标记流 会根据各自的情况,传递给特定的标记过滤器。

    标记过滤器可能修改,添加或删除标记。我们已经提过 lowercasestop 标记过滤器,但是 Elasticsearch 中有更多的选择。stemmer 标记过滤器将单词转化为他们的根形态(root form)。ascii_folding 标记过滤器会删除变音符号,比如从 très 转为 tresngramedge_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_strip 字符过滤器去除所有的 HTML 标签

    2. & 替换成 and,使用一个自定义的 mapping 字符过滤器

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

    2. 使用 lowercase 标记过滤器将词转为小写

    3. stop 标记过滤器去除一些自定义停用词。

    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. }