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

修改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"
      }
    }
  }
}
'
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343