Elasticsearch文本分析之Analyzer使用

1. Analyzer概述

Elasticsearch使用Analyzer来实现文本分析,从而实现将非结构化文本(例如文章正文、邮件内容等)转换为结构化数据,便于检索。Analyzer用于两个场景:对文本字段进行索引和搜索文本。Analyzer只对配置之后的索引生效。

Analyzer包含3个构建块:

  1. Character filters,字符过滤器,接收原始文本,添加、删除或者改变原始文本的字符。例如HTML标签过滤等。1个Analyzer中可以有0个或者多个字符过滤器。
  2. Tokenizer, 分词器,接收经过字符过滤器后的字符流,对其进行分词。1个Analyzer中只能有1个Tokenizer。
  3. Token filters, 分词过滤器,接收经过分词器后的分词列表,添加、删除或者更改分词。例如大小写转换、同义词添加等。1个Analyzer中可以有0个或者多个分词过滤器。

Elasticsearch英文官网中对于以上3个构建块的表述很准确,字符过滤器和分词过滤器用的是复数,Character filters和Token filters,而Tokenizer用的是单数,表示只有1个。

以下通过REST API为例说明Analyzer的使用。

2. 配置Analyzer

ES内置了很多Analyzer,譬如standard analyzer,包含1个standard tokenizer、2个token filter:lower case token filter 和 stop token filter,可以不需要任何配置就应用到索引和搜索中。同样,Elasticsearch中也内置了大量Character filters和Token filters。

Elasticsearch也提供了插件开发接口,用于开发者自己编写Analyzer或者Tokenizer、Character filter和Token filter。譬如各类中文分词插件。

在实际场景中,通常需要通过组合配置分词插件、内置Analyzer、内置Tokenizer、内置Character filters和内置Token filters等来实现索引需求。

内置Analyzer(standard analyzer)可以不需要配置而直接应用到索引配置中,本节主要描述自定义的Analyzer。

自定义Analyzer有2种情况:

  1. 对内置Analyzer或者Analyzer插件的默认配置进行修改。

  2. 在内置Analyzer或者Analyzer插件的基础上,组合添加Tokenizer、Character filters和Token filters。

不管是哪种情况,都需要创建自定义的Analyzer,不能直接应用原有Analyzer。

2.1. 修改内置Analyzer的配置

内置Analyzer包括:

Fingerprint、Keyword、Language、Pattern、Simple、Standard、Stop、Whitespace。

以修改standard analyzer的属性为例。

standard analyzer可修改的属性如下:

官网参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html

  • max_token_length,最大token长度,默认为255。
  • stopwords,预定义的停止词列表名称,默认为none。预定义的停止词列表名称见https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stop-tokenfilter.html#analysis-stop-tokenfilter-stop-words-by-lang。
  • stopwords_path,预定义的停止词列表文件路径。

修改standard analyzer的默认属性如下:

curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_english_analyzer": {
          "type": "standard",
          "max_token_length": 5,
          "stopwords": "_english_"
        }
      }
    }
  }
}
'

为方便看request body的格式,扁平化一下,

settings.analysis.analyzer.<自定义分析器名称>
{
    "type": "standard",//这里填写要修改的内置分析器名称
    "max_token_length": 5,//这里是内置分析器可以修改的属性
    "stopwords": "_english_"//这里是内置分析器可以修改的属性
}

可以用下面的方法测试分词效果。

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

2.2. 组合内置模块

内置模块分为3类:Tokenizer、Filter、Char Filter。

  • Tokenizer: Character group, Classic, Edge n-gram, Keyword, Letter, Lowercase, N-gram, Path hierarchy, Pattern, Simple pattern, Simple pattern split, Standard, Thai, UAX URL, mail, Whitespace
  • Filter: Apostrophe, ASCII folding, CJK bigram, CJK width, Classic, Common grams, Conditional, Decimal digit, Delimited payload, Dictionary decompounder, Edge n-gram, Elision, Fingerprint, Flatten graph, Hunspell, Hyphenation decompounder, Keep types, Keep words, Keyword marker, Keyword repeat, KStem, Length, Limit token count, Lowercase, MinHash, Multiplexer, N-gram, Normalization, Pattern capture, Pattern replace, Phonetic, Porter stem, Predicate script, Remove duplicates, Reverse, Shingle, Snowball, Stemmer, Stemmer override, Stop, Synonym, Synonym graph, Trim, Truncate, Unique, Uppercase, Word delimiter, Word delimiter graph
  • Char Filter: HTML strip, Mapping, Pattern replace

任意组合内置模块,生成自定义的分析器。例如:

curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom", 
          "tokenizer": "standard",
          "char_filter": [
            "html_strip"
          ],
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  }
}
'

为方便看request body的格式,扁平化一下,

settings.analysis.analyzer.<自定义分析器名称>
{
    "type": "custom",//这里填写custom,因为要自己组装内置模块形成一个自定义分析器。
    "tokenizer": "standard",,//tokenizer, 字符串,内置tokenizer名称
    "char_filter": ["html_strip"],//char_filter,数组,内置char_filter列表
    "filter": [ "lowercase", "asciifolding" ] //filter,数组,内置filter列表
}

简言之,格式为从内置模块中,选择1个tokenizer,0个或多个char_filter,0个或多个filter。

2.3. 所有模块自定义

与2.2相比,这里对内置模块的属性也进行了修改,将修改属性后的内置模块组合成自定义分析器Analyzer。属于最通用的自定义分析器。

例如:

curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": { 
          "type": "custom",
          "char_filter": [
            "emoticons"
          ],
          "tokenizer": "punctuation",
          "filter": [
            "lowercase",
            "english_stop"
          ]
        }
      },
      "tokenizer": {
        "punctuation": { 
          "type": "pattern",
          "pattern": "[ .,!?]"
        }
      },
      "char_filter": {
        "emoticons": { 
          "type": "mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": {
        "english_stop": { 
          "type": "stop",
          "stopwords": "_english_"
        }
      }
    }
  }
}
'

为方便看request body的格式,扁平化一下,

settings.analysis.analyzer.<自定义分析器名称>
{
    "type": "custom",//这里填写custom,因为要自己组装自定义模块形成一个自定义分析器。
    "tokenizer": "自定义tokenizer名称",,//tokenizer, 字符串,内置tokenizer或者自定义tokenizer名称
    "char_filter": ["自定义char_filter名称"],//char_filter,数组,内置char_filter和自定义char_filter列表
    "filter": [ "lowercase", "自定义filter名称" ] //filter,数组,内置filter和自定义filter列表
}
settings.analysis.tokenizer.<自定义tokenizer名称>
{
    "type": "pattern", //要修改的tokenizer类型名称
    "pattern": "[ .,!?]" //要修改的属性
}
settings.analysis.char_filter.<自定义char_filter名称>
{
    "type":"mapping", //要修改的char_filter类型名称
    "mappings":[balabala...] //要修改的属性
}
settings.analysis.filter.<自定义filter名称>
{
    "type":"stop", //要修改的filter类型名称
    "stopwords": "_english_" //要修改的属性
}

简言之,格式为在analysis的子节点中添加各种自定义模块,从中选择1个tokenizer,0个或多个char_filter,0个或多个filter组成自定义分析器Analyzer。

3. 应用Analyzer

Analyzer应用在2个场景:

  • 索引(index,在索引中插入数据时进行文本分析)
  • 搜索(search,搜索时对搜索词进行文本分析)

3.1. 索引场景

指定index的分析器Analyzer。

大多数情况下,在创建index时,在mapping参数中为每一个text field都指定一下analyzer是最好的实践。这样的情况下,使用[indexName]/_mapping就能看到每一个text字段的分词器设置。用index templates也可以。

3.1.1. 为某个字段指定分析器

创建索引index时,在mapping参数中指定。

curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "whitespace"
      }
    }
  }
}
'

3.1.2. 为index指定默认的分析器

创建或者更新index的settings时,指定analysis.analyzer.default参数。参数值的类型就是自定义analyzer的类型。

curl -X PUT "172.22.69.39:9210/ibase-reserved-ansj/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "analysis": {
      "analyzer": {
        "cmpv2_ansj": { 
          "type": "custom",
          "tokenizer": "index_ansj",
          "char_filter": [
            "html_strip"
          ]
        },
        "default": { 
          "type": "custom",
          "tokenizer": "index_ansj",
          "char_filter": [
                "html_strip"
          ]
        }
      }
    }
  }
}
'

3.2. 搜索场景

指定搜索的分析器。

3.2.1. search检索中,指定分析器。

curl -X GET "localhost:9200/my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "message": {
        "query": "Quick foxes",
        "analyzer": "stop"
      }
    }
  }
}
'

3.2.2. 在创建index时,mapping参数中,指定text字段的search_analyzer参数。

curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "whitespace",
        "search_analyzer": "simple"
      }
    }
  }
}
'

3.2.3. 在创建index时,在analysis.analyzer参数中,指定default_search字段。即analysis.analyzer.default_search参数。如果设置这个参数,那么analysis.analyzer.default参数也得设置。

curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "simple"
        },
        "default_search": {
          "type": "whitespace"
        }
      }
    }
  }
}
'

如果上面3种都没有设置,那么会使用field中的analyzer参数值。也就是index时的analyzer。

4. 测试Analyzer

可以直接使用/_analyze来测试分词效果。

curl -X POST "localhost:9200/my-index-000001/_analyze?pretty" -H 'Content-Type: application/json' -d'
{
  "analyzer": "my_custom_analyzer",
  "text": "I\u0027m a :) person, and you?"
}
'

也可以使用/_search来检索

curl -X GET "localhost:9200/my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "message": {
        "query": "Quick foxes",
        "analyzer": "stop"
      }
    }
  }
}
'

你可能感兴趣的:(Elasticsearch文本分析之Analyzer使用)