elasticsearch analysis模块 自定义分词 拼音分词 同义词 停词

Analysis

Analysis 解析器由三个模块=character filters(字符过滤器), tokenizers(标记器), and token filters(标记过滤器)组成

Analysis 中的自定义分词

analysis 基本概念 === 全文索引中会用到Tokenizer(分词器)对文档分词,提取token(词元),讲token进一步处理如大小写转换的算法叫Filter(过滤器)。

所以当提供的分词器不满足我们使用时,比如中文分词,我们需要自定义分词
自定义分词结构如下
在这里插入图片描述

正常来说,我们可以在mapping中创建索引时设置analyzer指定,但是对于更多的分词需求就要自定义分词来达到想要的效果

需求:需要对中文分词,同义词转换,特殊字符过滤,html过滤
在这里插入图片描述

PUT /test
{
    "settings": {
      "analysis": {
        "analyzer":{//自定义分词
           "my_test_analyzer":{
             "type":"custom",          //自定义类型
             "tokenizer": "ik_smart",  //分词器
             "filter":["lowercase","my_synonym"],//使用带配置
             "char_filter":["mapping_filter","html_filter"]  //使用带配置
           }
        },
        "char_filter": {
          "html_filter":{
            "type":"html_strip"
          },
          "mapping_filter":{
            "type":"mapping",
            "mappings": [
              "yi=>一",//需要转换的字符
              "er=>二",
              "Π=>n"
            ]
          }
        },
        "filter": {
          "my_synonym":{//同义词
            "type":"synonym",
            "synonyms":[
              "工商,工行=>中国工商银行",
              "农行=>中国农业银行"
            ]
          }
        }
    }
  }
}

看下分词结果

GET test/_analyze
{
  "text": ["<p>我们在工行?Whats YOU Πame</p>"],
  "analyzer": "my_test_analyzer"
}

在这里插入图片描述

常用分词配置

https://www.elastic.co/guide/en/elasticsearch/reference/7.16/analysis.html

Tokenizers(分词器)

letter 非字母时分割文本

GET _analyze
{
  "text": "你是谁 阿克苏德拉科时间到了",
  "tokenizer": "letter"
}

在这里插入图片描述

lowercase 非字母分割+转为小写

# lowercase 非字母时分割文本+元转为小写
GET _analyze
{
  "text": "WHO Are You1so",
  "tokenizer": "lowercase"
}

在这里插入图片描述

whitespace 空格分割文本

GET _analyze
{
  "text": "WHO You,你 是谁",
  "tokenizer": "whitespace"
}

在这里插入图片描述
###uax_url_email URL ,email 词元

GET _analyze
{
  "text": "http://localhost:8080/api是:111111111@163.com",
  "tokenizer": "uax_url_email"
}

在这里插入图片描述

char_group 自定义标记语法

POST _analyze
{
  "tokenizer": {
    "type": "char_group",
    "tokenize_on_chars": [
      "whitespace",//空格
      "-"//自定义

    ]
  },
  "text": "我的Email 是-111111111@163.com"
}
  • letter  —单词  for example a, b, ï or 京
  • digit —  数字for example 3 or 7
  • whitespace — 空格  for example " " or “\n”
  • punctuation — 标点符号 for example ! or "
    -symbol — 符号 for example $ or √
    在这里插入图片描述

edge_ngram 从词语的最左侧逐一分词

POST _analyze
{
  "tokenizer": {
    "type": "edge_ngram",
    "min_gram": 2,//最小长度
    "max_gram": 6,//最大长度
    "token_chars":[//应包含在词元中的字符类。es将分割不属于指定类的字符 []为全部
      "letter",//对单词分词
      "digit"//对数字分词
    ]  
  },
  "text": "这是中文123456789"
}

在这里插入图片描述

N-grams 是一个连续的指定长度的字符序列

max_gram和min_gram的差值必须小于或等于:[1]

POST _analyze
{
  "tokenizer": {
    "type": "ngram",
    "min_gram": 3,//连续最小词数量
    "max_gram": 4,//连续最大词数量
    "token_chars":[//处理词的范围
      "letter",
      "digit", 
      "whitespace"
    ]
  },
  "text": "是中文1234 驱蚊器"
}

在这里插入图片描述

path_hierarchy路径层次分词

POST _analyze
{
  "tokenizer": {
    "type": "path_hierarchy",
    "skip":0,//忽视初始词量  就是删除前n个分词 默认0
    "delimiter":"/",//分隔符  默认/
    "replacement":"#" ,//路径分隔符替换 默认是delimiter
    "reverse":false//以相反的顺序发射词元。默认是 false 。
  },
  "text": "/usr/local/tomcat"
}

在这里插入图片描述

keyword 整词

POST _analyze
{
  "analyzer": "keyword",
  "text": "你猜我是谁"
}

Token Filters(词元过滤器)

Apostrophe (撇号/单引号过滤器)

中文不生效

GET /_analyze
{
  "tokenizer" : "standard",
  "filter" : ["apostrophe"],
  "text" : "it's"
}

在这里插入图片描述

Keep Types (保留指定类型过滤器)

GET _analyze
{
  "tokenizer": "standard",
  "filter": [
    {
      "type": "keep_types",
      "types": [ "<NUM>" ]
    }
  ],
  "text": "2012年12月12"
}
  • 字母
  • 韩语
  • 数字
    在这里插入图片描述

keep (保留字过滤器)

GET _analyze
{
  "tokenizer": "ik_smart",
  "filter": [
    {
      "type": "keep",
      "keep_words": [ "一只","我","一只量"]
    }
  ],
  "text": "我是一只量"
}

在这里插入图片描述

stop停词

英文分词中有指定的停词,IK中文分词内也有指定停词

GET /_analyze
{
  "tokenizer": "ik_smart",
    "filter": [
    {
      "type": "stop",
      "stopwords": [ "一只","我","一只量"]
    }
  ],
  "text": "我是一只量"
}

在这里插入图片描述

trim去除左右空格

GET _analyze
{
  "tokenizer" : "keyword",
  "filter" : ["trim"],
  "text" : " 你好 呀"
}

在这里插入图片描述

Character Filters(字符过滤器)

html_strip 过滤

POST _analyze
{
  "tokenizer":      "keyword", 
  "char_filter":{
    "type":"html_strip",
    "escaped_tags":["b"]//排除标签
  },
  "text": "<p>这是P标签<b>happy</b>!</p>"
}

在这里插入图片描述

mapping 字符过滤转换

GET /_analyze
{
  "tokenizer": "keyword",
  "char_filter": [
    {
      "type": "mapping",
      "mappings": [
        "yi=>一",//需要转换的字符
        "er=>二",
        "san=>三"
      ]
    }
  ],
  "text": "跟我说yiersan"
}

在这里插入图片描述

IK分词器+热更新

请看我另一篇文章
https://blog.csdn.net/crazyo2jam/article/details/107894090

拼音分词

https://github.com/medcl/elasticsearch-analysis-pinyin

分词设置说明

keep_first_letter : 刘德华>ldh, 默认: true
keep_separate_first_letter: 刘德华>l,d,h, 默认: false,由于词条太频繁,查询结果可能太模糊
limit_first_letter_length:设置第一个_字母结果的最大长度,默认值:16
keep_full_pinyin : 刘德华> [liu,de,hua], 默认: true
keep_joined_full_pinyin : 刘德华> [liudehua], 默认: false
keep_none_chinese:在结果中保留非中文字母或数字,默认值:true
keep_none_chinese_together将非中文字母保持在一起,默认值:true,例如:DJ音乐家->DJ,yin,yue,jia,当设置为false时,例如:DJ音乐家->D,J,yin,yue,jia,注意:keep_none_chinese应该首先启用
keep_none_chinese_in_first_letter在第一个字母中保留非中文字母 : 刘德华AT2016->ldhat2016, 默认: true
==keep_none_chinese_in_joined_full_pinyin == 将非中文字母保留在拼音拼音中 刘德华2016->liudehua2016, 默认: false
none_chinese_pinyin_tokenize 如果非中文字母是拼音,则将其拆分成单独的拼音项,默认值为true,例如:liudehuaalibaba13zhuanhan->liu,de,hua,a,li,ba,ba,13,zhuang,han,注意:keep_none_chinese和keep_none_chinese_组合在一起应该首先启用
keep_original 保持原始当此选项启用时,也将保持原始输入,默认值:false
lowercase 小写小写非中文字母,默认为true
trim_whitespace default: true
remove_duplicated_term 启用此选项后,将删除重复的术语以保存索引,例如:de的>de,默认值:false,注意:位置相关的查询可能会受到影响
ignore_pinyin_offset 6.0以后,对偏移量有严格的约束,不允许重叠令牌,有了这个参数,忽略偏移量将允许重叠令牌,请注意,所有与位置相关的查询或高亮显示都将不正确,您应该使用多个字段,并针对不同的查询目的指定不同的设置。如果需要偏移,请将其设置为false。默认值:true。

DELETE my_index

PUT my_index
{
    "settings": {
    "analysis": {
        "analyzer": {
            "ik_pinyin_analyzer": {
                "type": "custom",
                "tokenizer": "ik_smart",
                "char_filter": ["emoticons"],
                "filter":["lowercase","my_stop","my_pinyin", "word_delimiter"] 
            },
            "ik_smart_synonym_analyzer": { 
              "type": "custom",
              "tokenizer": "ik_smart",
              "char_filter": ["emoticons"],
              "filter": ["lowercase","my_stop","my_synonym_filter"]
            },
            "ik_max_word_synonym_analyzer": { 
              "type": "custom",
              "tokenizer": "ik_max_word",
              "char_filter": ["emoticons"],
              "filter": ["lowercase","my_stop","my_synonym_filter"]
            }
        },
        "char_filter": {
          "emoticons": { 
            "type": "mapping",
            "mappings": [
              "一 => 衣",
              ":( => _sad_"
            ]
          }
        },
        "filter":{
            "my_pinyin":{
                "type" : "pinyin",
                "keep_separate_first_letter" : false,
                "keep_joined_full_pinyin": true,
                "keep_original" : true,
                "limit_first_letter_length" : 16,
                "lowercase" : true,
                "remove_duplicated_term" : true
            },
            "my_stop": { 
              "type": "stop",
              "stopwords": "的"
            },
            "my_synonym_filter": {
             "type": "synonym",
             "synonyms_path": "analysis/synonyms.txt"
            }
        }
    }
  },
  "mappings": {
      "properties" : {
        "context" : {
          "type" : "text",
          "analyzer" : "ik_smart_synonym_analyzer",
           "fields": {
              "pinyin": {
                  "type": "text",
                  "term_vector": "with_positions_offsets",
                  "analyzer": "ik_pinyin_analyzer",
                  "boost": 10
               }
           }
        }
      }
  }
}


POST my_index/_doc/1
{
  "context":"我爱祖国"
}

POST my_index/_doc/2
{
  "context":"我是程序员"
}

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "context": "程序员"
          }
        }
      ]
    }
  }
}

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "context.pinyin": "chengxvyuan"
          }
        }
      ]
    }
  }
}

说明

"analysis": {  ##分词设置
        "analyzer": { ##自定义分词器 
            "ik_pinyin_analyzer": { ##分词器名子
                "type": "custom", ##类型  custom为自定义
                "tokenizer": "ik_smart",   ##分词器 IK
                "char_filter": ["emoticons"],  ##特殊字符转换
                "filter":["lowercase","my_stop","my_pinyin", "word_delimiter"]  
                ##使用的过滤器  (其实就是我们配置的分词种类)
            }, 
        },
        "char_filter": { ##字符转换
          "emoticons": { 
            "type": "mapping",
            "mappings": [
              "一 => 衣",
              ":( => _sad_"
            ]
          }
        },
        "filter":{  ##过滤器设置
            "my_pinyin":{   ##名字   下面是过滤器设置  这个是看官网的api写
                "type" : "pinyin",
                "keep_separate_first_letter" : false,
                "keep_joined_full_pinyin": true,
                "keep_original" : true,
                "limit_first_letter_length" : 16,
                "lowercase" : true,
                "remove_duplicated_term" : true
            },
            "my_stop": { ##停词  不过IK已经带停词词典了
              "type": "stop",
              "stopwords": "的"
            },
            "my_synonym_filter": {  ##同义词设置    
             "type": "synonym",
             "synonyms_path": "analysis/synonyms.txt"  ##路径必须在es在的conf内
            }
        }
    }

我测试的是IK+同义+拼音的组合是有问题的
所以我们把同义和拼音分开 mapping中通过

 "fields": {
              "pinyin": {
                  "type": "text",
                  "term_vector": "with_positions_offsets",
                  "analyzer": "ik_pinyin_analyzer",
                  "boost": 10
               }
           }

通过字段.pinyin使用拼音分词

另外 设置拼音分词的时候不可以设置 search_analyzer
这样子会导致我们使用拼音分词时必须字与字之间有分隔才可以识别
比如 liudehua 是搜不出来的 liu de hua 是可以的
应该是分词的问题导致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值